# coding=utf-8

from functools import cache

import datetime, re



# Create your views here.

# import mx.DateTime

from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.core.mail import send_mail
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import *
from django.http import Http404, HttpResponse, HttpResponseRedirect, JsonResponse
#from django.newforms import form_for_instance
from django.shortcuts import *
# from django.shortcuts import render
from django.template import RequestContext
from django.urls import reverse_lazy
# from django.utils import simplejson
from django.views.generic import *

import django.core.serializers

# from cachier import cachier
from dal import autocomplete
from datatableview import Datatable, columns, helpers
from datatableview.views import DatatableView, XEditableDatatableView
from django_tables2 import SingleTableView
from rest_framework import generics, viewsets

from .forms import *
from .models import *
from .serializers import *
from .tables import *

from .common import AddPatient, SortNHI, UpdateNHICase, QueryMS

#import ntuhgov.intra as intra
import ntuhgov.portal
# import ntuhgov import portal_spynner3 as portal_spynner 
# from ntuhgov import portal_spynner3 as portal 
# from ntuhgov import portal_ghost_xvfb as portal 
from ntuhgov import portal_selenium as portal 

# from . import kd22

import logging
logger = logging.getLogger(__name__)


# @cache
# @cachier(next_time=True)
def top_icd10(q=None):
    # qs = ICD10CMfinal.objects.annotate(count=Count('treatment')).order_by('-count')
    # if q:
    #     qs = qs.filter(
    #                     Q(ICD10CM__istartswith=q)
    #                     | Q(ICD9CM_code__istartswith=q)
    #                     | Q(ICD10CM_English__icontains=q)
    #                     | Q(ICD9CM_English__icontains=q))
    # return qs

    if q is None:
        return ICD10CMfinal.objects.all().order_by('-icd10count__count')
        return ICD10CMfinal.objects.all()
        return ICD10CMfinal.objects.annotate(count=Count('treatment')).order_by('-count')
    return top_icd10(None).filter(
        Q(ICD10CM__istartswith=q)
        | Q(ICD9CM_code__istartswith=q)
        | Q(ICD10CM_English__icontains=q)
        | Q(ICD9CM_English__icontains=q))

@cache
def top_icd10_list(n):
    return [x.ICD10CM for x in ICD10CMfinal.objects.all().order_by('-icd10count__count')[:n]]


class ICD10Autocomplete(autocomplete.Select2QuerySetView):
    def get_queryset(self):
        # Don't forget to filter out results depending on the visitor !
        if not self.request.user.is_authenticated:
            return ICD10CMfinal.objects.none()

        # qs = ICD10CMfinal.objects.all()
        qs = top_icd10(self.q)
            
        return qs


def top_icd10_list_dict(request):
    # a = top_icd10()
    # print(type(a))
    # for i in a:
    #     print(i, type(i))
    #     break
    count=10
    # return JsonResponse(list(top_icd10()[:count].values()), safe=False)
    return JsonResponse(list(top_icd10().values()[:count]), safe=False)

class CreateForPatient(CreateView):
    # def get_initial(self):
    #     patient = get_object_or_404(Patient, pk=self.kwargs.get('patient_id'))
    #     return {
    #         'patient': patient,
    #     }
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["patient"] = get_object_or_404(Patient, pk=self.kwargs.get('patient_id'))
        return context


class CreateEventForTreatment(CreateView): 
    fields = '__all__'
    def get_initial(self):
        treatment = get_object_or_404(Treatment, pk=self.kwargs.get('treatment_id'))
        return {
            'treatment': treatment,
        }



@login_required
def patient_add(request):
    if request.method == 'GET':
        parameters = request.GET
    elif request.method == 'POST':
        parameters = request.POST
        
    chartno = parameters.get('ChartNo', '')
    name = parameters.get('Name', '')
    idcode = parameters.get('idcode', '')
    force = parameters.get('force', '')

    # p = AddPatient({'IdNo': idcode, 'ChartNo': chartno,}, force=force)
    
    r = portal.QueryModifyPatBase({'IdNo': idcode,
                                                        'ChartNo': chartno,
                                                        })

    if r:
        r['name'] = r['ChtName']
        r['medical_records'] = r['ChartNo']
        r['gender'] = r['Sex']
        r['birthday'] = r['Birth']
        r['address'] = r['AddressControl1']
        r['phone'] = r['ContTel']
        r['id_cards'] = r['IdNo']
        
        result = [r]
    else:
        result = []  

    if force and len(result)>0:
        r=result[0]
        
        if r['gender'] == 'M':
            r['gender'] = 1
        else:
            r['gender'] = 2
#        hw = intra.HeightWeight(r['id_cards'])
#         hw = ntuhgov.portal.HeightWeight(r['id_cards'])
        hw = portal.BriefHistoryLink(r['id_cards'])
        p = Patient(name = r['name'],
                    medical_records = r['medical_records'],
                    gender = r['gender'],
                    birthday = r['birthday'],
                    address = r['address'],
                    phone = r['phone'],
                    id_cards = r['id_cards'],
                    # height = hw['Height'],
                    # weight = hw['weight'],
           )

        try:
            p.height = int(hw['Height'])
        except:
            pass
        try:
            p.weight = int(hw['Weight'])
        except:
            pass
        p.save()
        return HttpResponseRedirect('/patient/detail/%d/' % p.id)

    form = PatientForm()
    return render(request, 'ck/patient_add.html', 
                              {
                               'form': form,
                               'result': result,
                               }
        )
    return render_to_response('ck/patient_add.html',
                              {
                               'form': form,
                               'result': result,
                               }, context_instance=RequestContext(request))

@login_required
def patient_detail(request, object_id):
    if object_id=='':
        object_id = request.session.get('patient')
    patient = Patient.objects.get(id=object_id)
    if object_id:
        qset = (
            Q(patient=object_id)
        )
        treatments = Treatment.objects.filter(qset).distinct()
    else:
        treatments = []

# update patient timestamp

#    ts = patient.timestamp.date()
#    for treatment in treatments:
#        if treatment.date_completed > ts:
#            ts = treatment.date_completed
#    if patient.timestamp.date() != ts:
#        patient.timestamp = datetime.datetime.combine(ts, patient.timestamp.time())
#        patient.save()

    pacsimages = PACSImage.objects.filter(Q(patient=object_id),Q(Modality__startswith='CT')|Q(Modality__startswith='MR')).order_by('-ExamDate')
    if len(pacsimages) > 9:
        pacsimages = pacsimages[0:9]

    # response = render_to_response("ck/patient_detail.html",
    #                           {
    #                            "patient": patient,
    #                            "treatments": treatments,
    #                            "pacsimages": pacsimages,
    #                           }, context_instance=RequestContext(request))
    response = render(request, "ck/patient_detail.html",
                              {
                               "patient": patient,
                               "treatments": treatments,
                               "pacsimages": pacsimages,
                              }
        )
    response.set_cookie('patient', object_id)
    request.session['patient'] = object_id
    return response

@login_required
def patient_follow(request):
    pass


@login_required
def patient_print(request, object_id):
    if object_id=='':
        object_id = request.session.get('patient')
    patient = Patient.objects.get(id=object_id)
    if object_id:
        qset = (
            Q(patient=object_id)
        )
        treatments = Treatment.objects.filter(qset).distinct()
    else:
        treatments = []

# update patient timestamp

#    ts = patient.timestamp.date()
#    for treatment in treatments:
#        if treatment.date_completed > ts:
#            ts = treatment.date_completed
#    if patient.timestamp.date() != ts:
#        patient.timestamp = datetime.datetime.combine(ts, patient.timestamp.time())
#        patient.save()

    # response = render_to_response("ck/patient_print.html",
    #                           {
    #                            "patient": patient,
    #                            "treatments": treatments,
    #                           }, context_instance=RequestContext(request))
    response = render(request, "ck/patient_print.html",
                              {
                               "patient": patient,
                               "treatments": treatments,
                              }
        )
    response.set_cookie('patient', object_id)
    request.session['patient'] = object_id
    return response


@login_required
def patient_search(request):
    query = request.GET.get('q', '')
    if query:
        qset = (
            Q(medical_records__icontains=query) |
            Q(name__icontains=query) |
            Q(id_cards__iexact=query)
        )
        results = Patient.objects.filter(qset).distinct()
        if len(results) == 0:
            if re.match('^\d+', query):
                return HttpResponseRedirect('/patient/add/?ChartNo='+query)
            elif re.match('^\w\d+', query):
                return HttpResponseRedirect('/patient/add/?idcode='+query)
            else:
                return HttpResponseRedirect('/patient/add/?Name='+query)
    else:
        results = []
#    print "query=", query
#    print "results=", results
    return render(request, 'ck/patient_search.html', 
                              {
                               "results": results,
                               "query": query,
                              }
        )
    return render_to_response("ck/patient_search.html",
                              {
                               "results": results,
                               "query": query,
                              }, context_instance=RequestContext(request))




class PatientDatatableView(XEditableDatatableView):
    model = Patient

    class datatable_class(Datatable):

        gender_display = columns.TextColumn   ('Gender1', sources=['get_gender_display'])

        detail         = columns.DisplayColumn('Detail'    , processor='ProcessDetail')
        operations     = columns.DisplayColumn('Operations', processor='ProcessOperations')
        
        def ProcessDetail(self, *args, **kwargs):
            data = args[0]
            return f'''
            <a href="{reverse('patient-detail', kwargs={'object_id': data.id})}"><span class="material-icons-outlined">launch</span></a> 
            '''

        def ProcessOperations(self, *args, **kwargs):
            data = args[0]
            # print(data)
            # default_value = kwargs['default_value']
            return f'''
            <a href="{reverse('patient-update', kwargs={'pk': data.id})}"><span class="material-icons-outlined">edit</span></a> 
            <a href="{reverse('patient-delete', kwargs={'pk': data.id})}"><span class="material-icons-outlined">delete</span></a> 
            '''

        class Meta:
            ordering = ['-id'] 

            columns = [
                'detail',

                'id',
                'name',
                'medical_records',
                'gender_display',
                'birthday',
                # 'address',
                'phone',
                'id_cards',
                'memo',
                'dead',

                'operations',
            ]

            processors = { 
                'memo': helpers.make_xeditable(),
            }

# django-tables2 
# class PatientListView(ListView):
class PatientListView(SingleTableView):
    model = Patient
    table_class = PatientTable    
    # template_name = 'tutorial/people.html'

# django-rest-framework-datatables 
class PatientViewSet(viewsets.ModelViewSet):
    queryset = Patient.objects.all().order_by('name')
    serializer_class = PatientSerializer



@login_required
def prior_oncrt_query(request, object_id):
    if object_id=='':
        object_id = request.session.get('patient')
    patient = Patient.objects.get(id=object_id)
    priors = patient.priortreatment_set;

    answers = intra.oncrt_query(patient.medical_records)

#    return HttpResponse(str(answers))

    for answer in answers:
        if answer['way'] != 'Radiosurgery' and not priors.filter(date=answer['start_date']):
            p = PriorTreatment(
                patient = patient,
                date = answer['start_date'],
                treatment = 3,
                period = 1,
                dose = answer['total_dose'],
                memo = answer['site'] + ' ' + answer['remarks'],
            )
            p.save()
    return HttpResponseRedirect('/patient/detail/'+object_id)


@login_required
def prior_op_note(request, object_id):
    if object_id=='':
        object_id = request.session.get('patient')
    patient = Patient.objects.get(id=object_id)
    priors = patient.priortreatment_set;

#    answers = intra.op_note_case(patient.medical_records)
    answers = ntuhgov.portal.op_note_case(patient.medical_records)

#    return HttpResponse(str(answers))

    for answer in answers:
        if not priors.filter(date=answer['surgery_date_time']):
            p = PriorTreatment(
                patient = patient,
                date = answer['surgery_date_time'],
                treatment = 1,
                memo = ' '.join([answer['division'], answer['name_surgery'], answer['surgeon']])
            )
            p.save()
    return HttpResponseRedirect('/patient/detail/'+object_id)

@login_required
def prior_path_exam(request, object_id):
    if object_id=='':
        object_id = request.session.get('patient')
    patient = Patient.objects.get(id=object_id)
    pathexams = patient.pathexam_set;

#    answers = intra.path_exam(patient.medical_records)
    import ntuhgov.xportal
    answers = ntuhgov.xportal.ReportPathology(patient.medical_records)

#    return HttpResponse(str(answers))

    for answer in answers:
        if not pathexams.filter(path_code=answer['PathCode']):
            p = PathExam(
                    patient           = patient,
            path_code         = answer['PathCode'],
            specimen_code     = answer['SpecimenCode'],
            specimen_get_date = answer['SpecimenGetDate'][:10].replace('/','-'),
            report_date       = answer['ReportDate'][:10].replace('/','-'),
            division          = answer['DepCode'],
            bed               = answer['WardNoRoomCoBedNo'],
            report            = answer['Result'],
        )

            p.save()
    return HttpResponseRedirect('/patient/detail/'+object_id)

@login_required
def query_height_weight(request, object_id):
    if object_id=='':
        object_id = request.session.get('patient')
    patient = Patient.objects.get(id=object_id)
#    hw = intra.HeightWeight(patient.id_cards)
    hw = ntuhgov.portal.HeightWeight(patient.id_cards)
    patient.height = hw['Height']
    patient.weight = hw['Weight']
    patient.save()

    return HttpResponseRedirect('/patient/detail/'+object_id)


@login_required
def record_weekly(request, date):
    if not date:
        date = mx.DateTime.today()

    Monday = mx.DateTime.DateTimeFrom(date) + mx.DateTime.RelativeDateTime(days=-6,weekday=(mx.DateTime.Monday,0))
    NextMonday = Monday + mx.DateTime.RelativeDateTime(days=+7)
    prevweek = mx.DateTime.DateTimeFrom(date) + mx.DateTime.RelativeDateTime(days=-7)
    nextweek = mx.DateTime.DateTimeFrom(date) + mx.DateTime.RelativeDateTime(days=+7)

    weekday = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']

    weekdate = {}
    d = Monday
    for day in weekday:
        weekdate[day] = d.strftime('%m/%d')
        d = d + mx.DateTime.RelativeDateTime(days=+1)

#    print NextMonday, NNMonday
    sMonday = str(Monday)
    sNextMonday  = str(NextMonday)
    qset1 = Q(DTSTART__range=(sMonday, sNextMonday))

    qset2 = Q(mode__exact=310) #310: 治療

    events = VEVENT.objects.filter(qset1, qset2).order_by('DTSTART')

    tids = []

    for event in events:
        tid = event.treatment.id
        if not tid in tids:
            tids.append(tid)

    treatments = []
    for tid in tids:
        t = Treatment.objects.get(id=tid);
        treatment = {
            'id': t.id,
            'icd9': t.icd9,
            'other_diagnosis': t.other_diagnosis,
            'accounting': t.get_accounting_display(),
            'dates': [],
            'surgeon': t.surgeon,
            'oncologist': t.oncologist,
            'referral': t.referral,
        }

        for event in events:
            if tid == event.treatment.id:
                treatment['dates'].append(event.DTSTART.date())

#        for lesion in Treatment.objects.get(id=tid).lesion_set:
#            treatment.


        treatments.append(treatment)



#    treatments = Treatment.objects.filter(id__in=tids)

    # response = render_to_response("ck/record_weekly.html",
    #                           {
    #                            "prevweek": prevweek.date,
    #                            "nextweek": nextweek.date,
    #                            "weeknumber": Monday.strftime('%G年 第%V週'),
    #                            "weekdate": weekdate,
    #                            "events": events,
    #                            "treatments": treatments,
    #                           }, context_instance=RequestContext(request))

    return render(request, 'ck/record_weekly.html', 
                              {
                               "prevweek": prevweek.date,
                               "nextweek": nextweek.date,
                               "weeknumber": Monday.strftime('%G年 第%V週'),
                               "weekdate": weekdate,
                               "events": events,
                               "treatments": treatments,
                              }
        )
    # return response


@login_required
def timetable_scheduling(request, date):
    if not date:
        date = mx.DateTime.today()

    Monday = mx.DateTime.DateTimeFrom(date) + mx.DateTime.RelativeDateTime(days=+6,weekday=(mx.DateTime.Monday,0))
    NextMonday = Monday + mx.DateTime.RelativeDateTime(days=+7)
    prevweek = mx.DateTime.DateTimeFrom(date) + mx.DateTime.RelativeDateTime(days=-7)
    nextweek = mx.DateTime.DateTimeFrom(date) + mx.DateTime.RelativeDateTime(days=+7)
#    print NextMonday, NNMonday
    sMonday = str(Monday)
    sNextMonday = str(NextMonday)
    qset = (
        Q(DTSTART__range=(sMonday, sNextMonday))
    )

    treatments = Treatment.objects.filter(output__id__lt=900)

    weekday = ['mon', 'tue', 'wed', 'thu', 'fri']

    weekdate = {}
    d = Monday
    for day in weekday:
        weekdate[day] = d.strftime('%m/%d')
        d = d + mx.DateTime.RelativeDateTime(days=+1)

    timetable = []
    for treatment in treatments:
        if treatment.vevent_set.filter(qset):
            r = {}
            patient = treatment.patient
            r['name'] = patient.name
            r['medical_records'] = patient.medical_records
            r['indications'] = str(treatment.surgeon) + '\n' + str(treatment.oncologist)
            r['diagnosis_site'] = treatment.other_diagnosis
            r['number'] = ''
            r['node'] = ''
            r['mode'] = ''
            r['time'] = ''
            r['actual_treatment'] = ''
            for day in weekday:
                r[day] = ''
            for event in treatment.vevent_set.order_by('DTSTART'):
                wd = (event.DTSTART.date() - datetime.datetime.fromtimestamp(Monday).date()).days
                if wd in range(0, 6):
                    r[weekday[wd]] += event.DTSTART.strftime('%H:%M') + ' ' + event.get_mode_display() + '\n'
            timetable.append(r)


#        print timetable

    # response = render_to_response("ck/timetable_scheduling.html",
    #                           {
    #                            "prevweek": prevweek.date,
    #                            "nextweek": nextweek.date,
    #                            "timetable": timetable,
    #                            "weekdate": weekdate,
    #                           }, context_instance=RequestContext(request))
    return render(request, 'ck/timetable_scheduling.html', 
                              {
                               "prevweek": prevweek.date,
                               "nextweek": nextweek.date,
                               "timetable": timetable,
                               "weekdate": weekdate,
                              }
        )
    return response


@login_required
def treatment_detail(request, object_id):
    if object_id=='':
        object_id = request.session.get('treatment')
    treatment = Treatment.objects.get(id=object_id)
    patient = Patient.objects.get(id=treatment.patient_id)
#    response.set_cookie('patient', patient.id)
    request.session['patient'] = patient.id
    if object_id:
        qset = (
            Q(treatment=object_id)
        )
        vevents = VEVENT.objects.filter(qset).distinct().order_by('DTSTART')
        lesions = Lesion.objects.filter(qset).distinct()
    else:
        vevents = []
        lesions = []

# update treatment date_completed

    for vevent in vevents:
        vevent.SUMMARY = vevent.treatment.patient.name + vevent.get_mode_display() 
        if vevent.mode_remark:
            vevent.SUMMARY += vevent.mode_remark
        vevent.save()

    ds = False
    dc = False

    for lesion in lesions:
        if lesion.start_date != None:
          if not ds or lesion.start_date < ds:
            ds = lesion.start_date
        if lesion.end_date != None:
          if not dc or lesion.end_date > dc:
            dc = lesion.end_date

    if not ds:
        for vevent in vevents:
            if vevent.mode != 310:
                continue
            if not ds or vevent.DTSTART.date() < ds:
                ds = vevent.DTSTART.date()
            if not dc or vevent.DTSTART.date() > dc:
                dc = vevent.DTSTART.date()

    if not ds:
        for vevent in vevents:
            if not ds or vevent.DTSTART.date() < ds:
                ds = vevent.DTSTART.date()
            if not dc or vevent.DTSTART.date() > dc:
                dc = vevent.DTSTART.date()

    if ds and treatment.date_started != ds:
        treatment.date_started = ds
        treatment.save()
    if dc and treatment.date_completed != dc:
        treatment.date_completed = dc
        treatment.save()

    nhiorders = NHIOrder.objects.filter(ChartNo=patient.medical_records)

    # response = render_to_response("ck/treatment_detail.html",
    #                           {
    #                            "patient": patient,
    #                            "treatment": treatment,
    #                            "vevents": vevents,
    #                            "lesions": lesions,
    #                           }, context_instance=RequestContext(request))
    response = render(request, 'ck/treatment_detail.html', 
                              {
                               "patient": patient,
                               "treatment": treatment,
                               "vevents": vevents,
                               "lesions": lesions,
                               "nhiorders": nhiorders,
                              }
        )
    response.set_cookie('patient', patient.id)
    request.session['patient'] = patient.id
    response.set_cookie('treatment', object_id)
    request.session['treatment'] = object_id
    return response
    


@login_required
def treatment_print(request, object_id):
    if object_id=='':
        object_id = request.session.get('treatment')
    treatment = Treatment.objects.get(id=object_id)
    patient = Patient.objects.get(id=treatment.patient_id)
    if object_id:
        qset = (
            Q(treatment=object_id)
        )
        vevents = VEVENT.objects.filter(qset).distinct().order_by('DTSTART')
        lesions = Lesion.objects.filter(qset).distinct()
    else:
        vevents = []
        lesions = []

# update treatment date_completed

    dc = treatment.date_completed

    for vevent in vevents:
        vevent.SUMMARY = vevent.treatment.patient.name + vevent.get_mode_display()
        if vevent.mode_remark:
            vevent.SUMMARY += vevent.mode_remark
        vevent.save()
        if vevent.DTSTART.date() > dc:
            dc = vevent.DTSTART.date()

    if treatment.date_completed != dc:
        treatment.date_completed = dc
        treatment.save()

    paginator = Paginator(lesions, 3) # Show 3 lesions per page

    # Make sure page request is an int. If not, deliver first page.
    try:
        page = int(request.GET.get('page', '1'))
    except ValueError:
        page = 1

    # If page request (9999) is out of range, deliver last page of results.
    try:
        contacts = paginator.page(page)
    except (EmptyPage, InvalidPage):
        contacts = paginator.page(paginator.num_pages)

    # response = render_to_response("ck/treatment_print.html",
    #                           {
    #                            "patient": patient,
    #                            "treatment": treatment,
    #                            "vevents": vevents,
    #                            "contacts": contacts,
    #                           }, context_instance=RequestContext(request))
    response = render(request, 'ck/treatment_print.html', 
                              {
                               "patient": patient,
                               "treatment": treatment,
                               "vevents": vevents,
                               "contacts": contacts,
                              }
        )
    response.set_cookie('patient', object_id)
    request.session['patient'] = object_id
    response.set_cookie('treatment', object_id)
    request.session['treatment'] = object_id
    return response


@login_required
def treatment_record(request, object_id):
    if object_id=='':
        object_id = request.session.get('treatment')
    treatment = Treatment.objects.get(id=object_id)
    patient = Patient.objects.get(id=treatment.patient_id)
    if object_id:
        qset = (
            Q(treatment=object_id)
        )
        vevents = VEVENT.objects.filter(qset).distinct().order_by('DTSTART')
        lesions = Lesion.objects.filter(qset).distinct()
    else:
        vevents = []
        lesions = []

# update treatment date_completed

    dc = treatment.date_completed

    for vevent in vevents:
        vevent.SUMMARY = vevent.treatment.patient.name + vevent.get_mode_display()
        if vevent.mode_remark:
            vevent.SUMMARY += vevent.mode_remark
        vevent.save()
        if vevent.DTSTART.date() > dc:
            dc = vevent.DTSTART.date()

    if treatment.date_completed != dc:
        treatment.date_completed = dc
        treatment.save()

#    response = render_to_response("ck/treatment_record.html",
    # response = render_to_response("ck/brief_history.html",
    #                           {
    #                            "patient": patient,
    #                            "treatment": treatment,
    #                            "vevents": vevents,
    #                            "lesions": lesions,
    #                           }, context_instance=RequestContext(request))
    response = render(request, 'ck/brief_history.html', 
                              {
                               "patient": patient,
                               "treatment": treatment,
                               "vevents": vevents,
                               "lesions": lesions,
                              }
        )
    response.set_cookie('patient', object_id)
    request.session['patient'] = object_id
    response.set_cookie('treatment', object_id)
    request.session['treatment'] = object_id
    return response


@login_required
def treatment_report(request, object_id):
    if object_id=='':
        object_id = request.session.get('treatment')
    treatment = Treatment.objects.get(id=object_id)
    patient = Patient.objects.get(id=treatment.patient_id)
    if object_id:
        qset = (
            Q(treatment=object_id)
        )
        vevents = VEVENT.objects.filter(qset).distinct().order_by('DTSTART')
        lesions = Lesion.objects.filter(qset).distinct()
    else:
        vevents = []
        lesions = []

# update treatment date_completed

    dc = treatment.date_completed

    for vevent in vevents:
        vevent.SUMMARY = vevent.treatment.patient.name + vevent.get_mode_display()
        if vevent.mode_remark:
            vevent.SUMMARY += vevent.mode_remark
        vevent.save()
        if vevent.DTSTART.date() > dc:
            dc = vevent.DTSTART.date()

    if treatment.date_completed != dc:
        treatment.date_completed = dc
        treatment.save()

    paginator = Paginator(lesions, 5) # Show 25 contacts per page

    # Make sure page request is an int. If not, deliver first page.
    try:
        page = int(request.GET.get('page', '1'))
    except ValueError:
        page = 1

    # If page request (9999) is out of range, deliver last page of results.
    try:
        contacts = paginator.page(page)
    except (EmptyPage, InvalidPage):
        contacts = paginator.page(paginator.num_pages)

    # response = render_to_response("ck/treatment_report.html",
    #                           {
    #                            "patient": patient,
    #                            "treatment": treatment,
    #                            "vevents": vevents,
    #                            "contacts": contacts,
    #                           }, context_instance=RequestContext(request))
    response = render(request, 'ck/treatment_report.html', 
                              {
                               "patient": patient,
                               "treatment": treatment,
                               "vevents": vevents,
                               "contacts": contacts,
                              }
        )
    response.set_cookie('patient', object_id)
    request.session['patient'] = object_id
    response.set_cookie('treatment', object_id)
    request.session['treatment'] = object_id
    return response


class TreatmentUpdate(UpdateView):
    model      = Treatment
    form_class = TreatmentForm

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        print(context)
        context["topicd10"] = top_icd10
        context['nhiorders'] = NHIOrder.objects.filter(ChartNo=self.object.patient.medical_records)
        return context


@login_required
def treatment_update(request, object_id):
    if request.method == 'POST':
#        TreatmentForm = form_for_model(Treatment)
        form = TreatmentForm(request.POST)
        # print dir(form)
        logging.info(dir(form))
        form.save()
        return HttpResponseRedirect('/treatment/list/')

    treatment = Treatment.objects.get(id=object_id)
    patient = Patient.objects.get(id=treatment.patient.id)
#    TreatmentForm = form_for_instance(treatment)
    form = TreatmentForm(instance=treatment)
#     response = render_to_response("ck/treatment_form2.html",
    # response = render_to_response("ck/treatment_form.html",
    #                           {
    #                            "form": form,
    #                            "patient": patient,
    #                           }, context_instance=RequestContext(request))
    response = render(request, "ck/treatment_form.html",
                              {
                               "form": form,
                               "patient": patient,
                              }
        )
    response.set_cookie('treatment', object_id)
    request.session['treatment'] = object_id
    return response


class TreatmentDatatableView(XEditableDatatableView):
    model = Treatment

    def setup(self, request, *args, **kwargs):
        super().setup(request, *args, **kwargs)
        if request.GET.get('download') is not None:
            QueryMS()

    class datatable_class(Datatable):


        patient_name = columns.TextColumn   ('Name', sources=['patient__name'])
        medical_records = columns.TextColumn   ('MRN', sources=['patient__medical_records'])
        date = columns.CompoundColumn('Date', sources=['date_started', 'date_completed'])
        get_accounting_display = columns.TextColumn   ('記帳', sources=['get_accounting_display'])

        # django.core.exceptions.FieldError: Related Field got invalid lookup: icontains
        icd10 = columns.TextColumn   ('ICD10', processor='ProcessICD10', sources=['icd10cm__ICD10CM']) 
        icd9  = columns.TextColumn   ('ICD9', processor='ProcessICD9', sources=['icd9__code'])

        detail          = columns.DisplayColumn('Detail'    , processor='ProcessDetail')
        operations      = columns.DisplayColumn('Operations', processor='ProcessOperations')
        
        def ProcessICD10(self, *args, **kwargs):
            data = args[0]

            if data.icd10cm is None:
                return f'<div class="bg-danger text-white">None</div>'
            if data.icd10cm.ICD10CM not in top_icd10_list(10):
                return f'<div class="bg-danger text-white" title="{data.icd10cm.ICD10CM_English}">{data.icd10cm.ICD10CM}</div>'
            if data.icd10cm.ICD10CM not in top_icd10_list(5):
                return f'<div class="bg-warning text-dark" title="{data.icd10cm.ICD10CM_English}">{data.icd10cm.ICD10CM}</div>'

            return f'<div class="bg-success text-white" title="{data.icd10cm.ICD10CM_English}">{data.icd10cm.ICD10CM}</div>'
            return str(data.icd10cm)
            if data.icd10cm is None:
                return None
            return f'<span title="{data.icd10cm.ICD10CM_English}">{data.icd10cm.ICD10CM}</span>'

        def ProcessICD9(self, *args, **kwargs):
            data = args[0]
            if data.icd9 is None:
                return '<div class="bg-danger text-white">None</div>'
            return f'<div class="bg-success text-white" title="{data.icd9.desc}">{data.icd9.code}</div>'
            return str(data.icd9)

        def ProcessDetail(self, *args, **kwargs):
            data = args[0]
            return f'''
            <a href="{reverse('treatment-detail', kwargs={'object_id': data.id})}"><span class="material-icons-outlined">launch</span></a> 
            '''

        def ProcessOperations(self, *args, **kwargs):
            data = args[0]
            # print(data)
            # default_value = kwargs['default_value']
            return f'''
            <a href="{reverse('treatment-update', kwargs={'pk': data.id})}"><span class="material-icons-outlined">edit</span></a> 
            <a href="{reverse('treatment-delete', kwargs={'pk': data.id})}"><span class="material-icons-outlined">delete</span></a> 
            '''

        class Meta:
            ordering = ['-id'] 

            columns = [
                'detail',

                'id',
                'patient_name',
                'medical_records',
                # 'date_started',
                # 'date_completed',
                'date',
                'oncologist',
                'surgeon',
                'get_accounting_display',
                'disease_stage',
                'primary_tumor_site',
                # 'icd10cm',
                'icd10',
                'icd9',
                'other_diagnosis',
                'input',
                'output',
                'bed',
                'memo',

                'operations',
            ]

            processors = { 
                'memo': helpers.make_xeditable(),
            }

            # request_method = 'POST' # make_xeditable will not work with post??

            # search_fields = [
            #     # 'patient__medical_records'
            #     'memo',
            # ]


class FinishedTreatmentDatatableView(TreatmentDatatableView):
    def get_queryset(self):
        queryset = super().get_queryset()
        return queryset.filter(**self.request.GET.dict())

@login_required
def followup_newimages(request):

    renew = request.REQUEST.get('renew', False)

    if renew:
        kd22.renew(PACSImage)

    date_query = Treatment.objects.values('patient_id').annotate(started=Min('date_started'),completed=Max('date_completed'))
    images = PACSImage.objects.filter(Q(Saved = 0),Q(Modality__startswith='CT')|Q(Modality__startswith='MR')).order_by('-ExamDate')[:100]
    results = []
    
    
    
    blank = 0
    
    for image in images:
        if blank > 50:
            break
        try:
            treat_date = date_query.get(patient=image.patient)
        except:
            continue
        if image.ExamDate > treat_date['completed']:
            try:
                LF = LesionFollow.objects.get(Q(Lesion__treatment__patient = image.patient),Q(Date = image.ExamDate))
                image.Saved = 10 #有輸入
            except:
                pass
            results.append(image)
            if image.Saved == 0:
                blank += 1 
                
    return render(request, "ck/followup_newimages.html",
                              {
                               "images": results,
                              }
        )
    return render_to_response("ck/followup_newimages.html",
                              {
                               "images": results,
                              }, context_instance=RequestContext(request))

@login_required
def followup_markimages(request, RequestSheetNo, Saved):
    image = PACSImage.objects.get(Q(RequestSheetNo = RequestSheetNo))
    image.Saved = Saved
    image.save()
    return HttpResponseRedirect('/followup/newimages/')

@login_required
def followup_nosee1(request):
    treatment_date = Treatment.objects.values('patient_id').annotate(first=Min('date_started'),last=Max('date_completed'))
    followup_date  = Followup.objects.values('patient_id').annotate(first=Min('date'),last=Max('date'))
    record_date    = MedicalRecord.objects.values('patient_id').annotate(first=Min('InDate'),last=Max('InDate'))
    image_date     = PACSImage.objects.values('patient_id').annotate(first=Min('ExamDate'),last=Max('ExamDate'))
    
    patients = Patient.objects.all()
    results = []
#    n = datetime.datetime.now()
    for patient in patients:
        if patient.dead:
            continue
        
        try:
            d = treatment_date.get(patient=patient)
            date = d['last']
        except:
#            print "%s no treatment" % patient.id
            continue

        try:
            d = followup_date.get(patient=patient)
            if d['last'] > date:
                date = d['last']
        except:
#            print "%s no follow" % patient.id
            pass

        try:
            d = record_date.get(patient=patient)
            if d['last'] > date:
                date = d['last']
        except:
#            print "%s no record" % patient.id
            pass

        try:
            d = image_date.get(patient=patient)
            if d['last'] > date:
                date = d['last']
        except:
#            print "%s no image" % patient.id
            pass
        
#        results['patient.id']=date
        results.append((patient, date))
        
#    print results
    results = sorted(results, key=lambda last: last[1])[:25]
#    print datetime.datetime.now() - n
#    print results
        
    return render(request, "ck/followup_nosee.html",
                              {
                               "results": results,
                              }
        )
    return render_to_response("ck/followup_nosee.html",
                              {
                               "results": results,
                              }, context_instance=RequestContext(request))

@login_required
def followup_nosee(request):
    ###Load all dates into hash first
    treatment_date = Treatment.objects.values('patient_id').annotate(first=Min('date_started'),last=Max('date_completed'))
    t = {}
    for item in treatment_date:
        t[item['patient_id']] = item['last']
        
    followup_date  = Followup.objects.values('patient_id').annotate(first=Min('date'),last=Max('date'))
    f = {}
    for item in followup_date:
        f[item['patient_id']] = item['last']
        
    record_date    = MedicalRecord.objects.values('patient_id').annotate(first=Min('InDate'),last=Max('InDate'))
    r = {}
    for item in record_date:
        r[item['patient_id']] = item['last']
        
    image_date     = PACSImage.objects.values('patient_id').annotate(first=Min('ExamDate'),last=Max('ExamDate'))
    i = {}
    for item in image_date:
        i[item['patient_id']] = item['last']
    
    patients = Patient.objects.all()
    results = []
#    n = datetime.datetime.now()
    for patient in patients:
        if patient.dead:
            continue
        
        try:
            d = t[patient.id]
            date = d
        except:
#            print "%s no treatment" % patient.id
            continue

        try:
            d = f[patient.id]
            if d > date:
                date = d
        except:
#            print "%s no follow" % patient.id
            pass

        try:
            d = r[patient.id]
            if d > date:
                date = d
        except:
#            print "%s no record" % patient.id
            pass

        try:
            d = i[patient.id]
            if d > date:
                date = d
        except:
#            print "%s no image" % patient.id
            pass
        
#        results['patient.id']=date
        results.append((patient, date))
        
#    print results
    results = sorted(results, key=lambda last: last[1])[:25]
#    print datetime.datetime.now() - n
#    print results

    model      = Patient
    form_class = None
    model, form_class = create_update.get_model_and_form_class(model, form_class)
    form = form_class()
        
    return render(request, "ck/followup_nosee.html",
                              {
                               "results": results,
                               "form": form,
                              }
        )
    return render_to_response("ck/followup_nosee.html",
                              {
                               "results": results,
                               "form": form,
                              }, context_instance=RequestContext(request))

@login_required
def followup_image_long(request):
    ###Load all dates into hash first
    treatment_date = Treatment.objects.values('patient_id').annotate(first=Min('date_started'),last=Max('date_completed'))
    t = {}
    for item in treatment_date:
        t[item['patient_id']] = item['first']
        
    image_date     = PACSImage.objects.filter(Saved__in=[0,10]).values('patient_id').annotate(first=Min('ExamDate'),last=Max('ExamDate'))
    i = {}
    for item in image_date:
        i[item['patient_id']] = item['last']

    v = {}
    follows = LesionFollow.objects.select_related().all()
#    print follows
    for follow in follows:
        if not v.has_key(follow.Lesion.treatment.patient.id):
            v[follow.Lesion.treatment.patient.id] = follow.Date
        else:
            v[follow.Lesion.treatment.patient.id] = max(follow.Date, v[follow.Lesion.treatment.patient.id])
        
#    print v


    
#    patients = Patient.objects.select_related().all()
    patients = Patient.objects.all()
    
    results = []
#    n = datetime.datetime.now()
#    print t
#    print i 
    for patient in patients:
        if patient.dead:
            continue
        
        try:
            d = t[patient.id]
            tdate = d
        except:
#            print "%s no treatment" % patient.id
            continue

        try:
            d = i[patient.id]
            idate = d
        except:
#            print "%s no image" % patient.id
            continue
        
        daydiff = (idate-tdate).days
        if daydiff < 365:
            continue
        
        try:
            d = v[patient.id]
            vdate = d
        except:
#            print "%s no image" % patient.id
            vdate = ''
            
        
        
#        results['patient.id']=date
        results.append((patient, daydiff, tdate, idate, vdate))
        
#    print type(idate-tdate)
#    print results
    results = sorted(results, key=lambda last: -last[1])
#    print datetime.datetime.now() - n
#    print results

#    model      = Patient
#    form_class = None
#    model, form_class = create_update.get_model_and_form_class(model, form_class)
#    form = form_class()
        
    return render(request, "ck/followup_image_long.html",
                              {
                               "results": results,
                              }
        )
    return render_to_response("ck/followup_image_long.html",
                              {
                               "results": results,
#                               "form": form,
                              }, context_instance=RequestContext(request))


@login_required
def followup_new_volume(request,object_id):
#    print request
#    print 'object_id=', object_id    
    
    idate = ''

    p = request.POST
#    print p
    if p.has_key('Lesion'):
        lesion = Lesion.objects.get(id=p['Lesion'])
        
        f = lambda x:None if x == '' else x
        
        l = LesionFollow(
            Lesion = lesion,
            Date = p['Date'],
            Volume = f(p['Volume']),
            A = f(p['A']),
            B = f(p['B']),
            C = f(p['C']),
            Memo = p['Memo'],
           )
        l.save()
        idate = p['Date']
        
    try:
        idate = request.GET['idate']
    except:
        idate = request.COOKIES['date']
    
    try:        
        patient = Patient.objects.get(id=object_id)
    except:
        patient = Patient.objects.get(id=request.COOKIES['patient'])

    model      = LesionFollow
    form_class = None
    model, form_class = create_update.get_model_and_form_class(model, form_class)
    form = form_class()
    
    # response = render_to_response("ck/followup_new_volume.html",
    #                           {
    #                            "patient": patient,
    #                            "idate": idate,
    #                            "form": form,
    #                           }, context_instance=RequestContext(request))
    response = render(request, "ck/followup_new_volume.html",
                              {
                               "patient": patient,
                               "idate": idate,
                               "form": form,
                              }
        )
    response.set_cookie('patient', patient.id)
    response.set_cookie('date', idate)
    return response

    
########## AJAX

@login_required
def below(request):
    return render(reuqest, 'ck/below.html')
    return render_to_response('ck/below.html')

@login_required
def get_target_location(request):
#    return HttpResponse(django.core.serializers.serialize("xml", TargetLocation.objects.all()))
    return HttpResponse(django.core.serializers.serialize("json", TargetLocation.objects.all()))

@login_required
def get_sublocation(request):
    i = request.GET.get('id', None)
    if i:
        return HttpResponse(django.core.serializers.serialize("json", SubLocation.objects.filter(id=i)))
    target = request.GET.get('target', None)
    return HttpResponse(django.core.serializers.serialize("json", SubLocation.objects.filter(target_location=target)))

@login_required
def get_pathology(request):
    sl = request.GET.get('sublocation', '')
    return HttpResponse(django.core.serializers.serialize("json", Pathology.objects.filter(sublocation=sl)))

def get_icd9cm(request):
    id = request.GET.get('id', False)
    name = request.GET.get('q', '')
    limit = request.GET.get('s', 99)

    if (name.count('.')):
        name = name.replace('.', '')[0:5].rstrip()
    if id:
        codes = ICD9Diag.objects.filter(code=id)
    elif len(name):
        qset = (
            Q(code__istartswith=name) |
#            Q(code__istartswith='0'+name) |
#            Q(code__istartswith='00'+name) |
            Q(desc__icontains=name)
        )
        codes = ICD9Diag.objects.filter(qset)[:100]
    else:
        codes =ICD9Diag.objects.all()[:100]
        
    ret = """
[  
"""
    
#    ret = '{"results":['  

    for code in codes:
#        ret += '["%s","%s"],' % (code.code, code)
        ret += '["%s","%s"],' % (code, code.code)
#        ret += '\n{"id":"%s","name":"%s"},' % (code.code, code)


    ret = ret[:-1]+"""
]  
"""


    return HttpResponse(ret)


def get_icd9cm_old(request):
    id = request.GET.get('id', False)
    name = request.GET.get('name', '')[:-1]
    if (name.count('.')):
        name = name.replace('.', '')[0:5].rstrip()
    if id:
        codes = ICD9Diag.objects.filter(code=id)
    elif len(name):
        qset = (
            Q(code__istartswith=name) |
#            Q(code__istartswith='0'+name) |
#            Q(code__istartswith='00'+name) |
            Q(desc__icontains=name)
        )
        codes = ICD9Diag.objects.filter(qset)[:100]
    else:
        codes =ICD9Diag.objects.all()[:100]
        
    ret = """
{ 'identifier': 'code',
  'label': 'name',
  'items': [
"""
    
#    ret = '{"results":['  

    for code in codes:
        ret += '\n{"code":"%s","name":"%s"},' % (code.code, code)
#        ret += '\n{"id":"%s","name":"%s"},' % (code.code, code)


    ret = ret[:-1]+"]}"


    return HttpResponse(ret)


def get_followup(request):
    date = request.GET.get('date', '')
    if date:
        d = mx.DateTime.DateTimeFrom(date)
        fr = d + mx.DateTime.RelativeDateTime(weeks=-6)
        to = d + mx.DateTime.RelativeDateTime(weeks=+6)
        events = Patient.objects.filter(next_followup__range=(fr, to))
    else:
        events = Patient.objects.all()

    return HttpResponse(django.core.serializers.serialize("json", events, ensure_ascii=False))


def get_vevent_old(request):
    date = request.GET.get('date', '')
    if date:
        d = mx.DateTime.DateTimeFrom(date)
        fr = d + mx.DateTime.RelativeDateTime(weeks=-6)
        to = d + mx.DateTime.RelativeDateTime(weeks=+6)
        events = VEVENT.objects.filter(DTSTART__range=(fr, to))
    else:
        events = VEVENT.objects.all()

    return HttpResponse(django.core.serializers.serialize("json", events, ensure_ascii=False))

# '''
# DataDumper
# '''
# 
# import types
# from django.db import models
# import pyxslt.serialize
# from django.utils import simplejson as json
# from django.core.serializers.json import DateTimeAwareJSONEncoder
# from decimal import *
# 
# class DataDumper:
#     fields = {}
#     def selectObjectFields(self,objectType,fields = []):
#         self.fields[objectType] = fields
# 
#     def dump(self,data,format='xml'):
#         """
#         The main issues with django's default json serializer is that properties that
#         had been added to a object dynamically are being ignored (and it also has 
#         problems with some models).
#         """
#     
#         def _any(data):
#             ret = None
#             if type(data) is types.ListType:
#                 ret = _list(data)
#             elif type(data) is types.DictType:
#                 ret = _dict(data)
#             elif isinstance(data, Decimal):
#                 # json.dumps() cant handle Decimal
#                 ret = str(data)
#             elif isinstance(data, models.query.QuerySet):
#                 # Actually its the same as a list ...
#                 ret = _list(data)
#             elif isinstance(data, models.Model):
#                 ret = _model(data)
#             else:
#                 ret = data
#             return ret
#         
#         def _model(data):
#             ret = {}
#             # If we only have a model, we only want to encode the fields.
#             objType = data.__class__.__name__
#             for f in data._meta.fields:
#                 if (self.fields[objType]) and (f.attname in self.fields[objType]):
#                     ret[f.attname] = _any(getattr(data, f.attname))
#             # And additionally encode arbitrary properties that had been added.
#             fields = dir(data.__class__) + ret.keys()
#             add_ons = [k for k in dir(data) if k not in fields]
#             for k in add_ons:
#                 if (self.fields[objType]) and (k in self.fields[objType]):
#                     ret[k] = _any(getattr(data, k))
#             return ret
#         def _list(data):
#             ret = []
#             for v in data:
#                 ret.append(_any(v))
#             return ret
#         
#         def _dict(data):
#             ret = {}
#             for k,v in data.items():
#                 ret[k] = _any(v)
#             return ret
#         
#         ret = _any(data)
#         if(format == 'xml'):
#             return pyxslt.serialize.toString(prettyPrintXml=False,data=ret,)
#         else:
#              return json.dumps(ret, cls=DateTimeAwareJSONEncoder)
# 
# '''
# DataDumper
# '''

@login_required
def get_vevent(request):
    events = VEVENT.objects.extra(select={
        'title' : "SUMMARY",
        'allDay': "false",
#        'start' : "UNIX_TIMESTAMP(DATE_SUB(DTSTART, INTERVAL 8 HOUR))",
#        'end' : "UNIX_TIMESTAMP(ADDTIME(DATE_SUB(DTSTART, INTERVAL 8 HOUR),DURATION))",
        'start' : "UNIX_TIMESTAMP(DTSTART)",
        'end' : "UNIX_TIMESTAMP(ADDTIME(DTSTART,DURATION))",
#        'end' : "UNIX_TIMESTAMP(ADDTIME(DTSTART,DURATION))",
#        'end' : "UNIX_TIMESTAMP(ADDTIME(DTSTART,MAX(DURATION,'00:30:00')))",
        'url'   : "CONCAT('/event/update/',id,'/')",
    })

    start = request.GET.get('start', '')
    end   = request.GET.get('end'  , '')

    if start:
        # fr = datetime.datetime.fromtimestamp(float(start))
        # to = datetime.datetime.fromtimestamp(float(end))
        fr = start
        to = end
        events = events.filter(DTSTART__range=(fr, to))

    # dumper = DataDumper()
    # dumper.selectObjectFields('VEVENT', ['id', 'title', 'allDay', 'start', 'end', 'url'])
    # dumper.dump(events,'json')

    # return HttpResponse(dumper.dump(events,'json'))

    return HttpResponse(django.core.serializers.serialize("json", events))

#    return HttpResponse(django.core.serializers.serialize("json", events, ensure_ascii=False))

#    entries = []
#    for event in events:
#        starttime = mx.DateTime.DateTimeFrom(event.DTSTART.isoformat())
#        duration = mx.DateTime.DateTimeDeltaFrom(hours=event.DURATION.hour, minutes=event.DURATION.minute)
#        endtime = starttime + duration
#        entry = {
#            'id': event.id,
#            'starttime': starttime.strftime('%Y-%m-%dT%H:%M:%S'),
#            'endtime': starttime.strftime('%Y-%m-%dT%H:%M:%S'),
#            'allday': False,
#            'repeated': False,
#            'title': event.treatment.patient.name + event.get_mode_display(),
#            'url': "/treatment/detail/%i/" % event.treatment.id,
#            'body': event.SUMMARY,
#            'attributes': {
#                'Oncologist': event.treatment.oncologist.name,
#                'Surgeon': event.treatment.surgeon.name,
#            },
#            'type': [event.get_mode_display(), event.get_mode_display()]
#        }
#        entries.append(entry)
#    return HttpResponse(django.core.serializers.serialize("xml", entries, ensure_ascii=False))

@login_required
def event_drop(request):

    id          = request.GET.get('id'         , '')
    dayDelta    = int(request.GET.get('dayDelta'   , ''))
    minuteDelta = int(request.GET.get('minuteDelta', ''))

    vevent = VEVENT.objects.get(id=id)
    t = vevent.DTSTART
    start = mx.DateTime.DateTime(t.year,t.month,t.day,t.hour,t.minute,t.second+1e-6*t.microsecond)
    start = start + mx.DateTime.RelativeDateTime(days=dayDelta) + mx.DateTime.RelativeDateTime(minutes=minuteDelta)
    vevent.DTSTART = datetime.datetime.fromtimestamp(start)
    vevent.save()

    return HttpResponse(django.core.serializers.serialize("json", VEVENT.objects.filter(id=id), ensure_ascii=False))

@login_required
def event_resize(request):

    id          = request.GET.get('id'         , '')
    dayDelta    = int(request.GET.get('dayDelta'   , ''))
    minuteDelta = int(request.GET.get('minuteDelta', ''))

    vevent = VEVENT.objects.get(id=id)
    t = vevent.DURATION
    d = datetime.timedelta(days=dayDelta,minutes=minuteDelta)
    dt = datetime.datetime.combine(datetime.date.today(), t) + d
    vevent.DURATION = dt.time()
    vevent.save()

    return HttpResponse(django.core.serializers.serialize("json", VEVENT.objects.filter(id=id), ensure_ascii=False))

@login_required
def update_vevent(request):

#    id = request.GET.get('id', '')
#    starttime = request.GET.get('starttime', '')
#    endtime = request.GET.get('endtime', '')

    id = request.POST.get('id', '')
    starttime = mx.DateTime.DateTimeFrom(request.POST.get('starttime', '')[:-6])
    endtime = mx.DateTime.DateTimeFrom(request.POST.get('endtime', '')[:-6])
    duration = mx.DateTime.Age(endtime, starttime)
    duration = str(duration.hours)+':'+str(duration.minutes)

    logging.info(id, starttime, endtime, duration)

    vevent = VEVENT.objects.get(id=id)
    vevent.DTSTART = starttime
#    vevent.DURATION = duration
    vevent.save()

    return HttpResponse(django.core.serializers.serialize("json", VEVENT.objects.filter(id=id), ensure_ascii=False))
#    return HttpResponse("")

        
def listCalendarByRange(sd, ed, cnt):
#    print ret
#    $title = array('team meeting', 'remote meeting', 'project plan review', 'annual report', 'go to dinner');
#    $location = array('Lodan', 'Newswer', 'Belion', 'Moore', 'Bytelin');
  
  
    events = VEVENT.objects.extra(select={
        'title' : "SUMMARY",
        'allDay': "false",
#        'start' : "UNIX_TIMESTAMP(DATE_SUB(DTSTART, INTERVAL 8 HOUR))",
#        'end' : "UNIX_TIMESTAMP(ADDTIME(DATE_SUB(DTSTART, INTERVAL 8 HOUR),DURATION))",
        'start' : "UNIX_TIMESTAMP(DTSTART)",
        'end' : "UNIX_TIMESTAMP(ADDTIME(DTSTART,DURATION))",
#        'end' : "UNIX_TIMESTAMP(ADDTIME(DTSTART,DURATION))",
#        'end' : "UNIX_TIMESTAMP(ADDTIME(DTSTART,MAX(DURATION,'00:30:00')))",
        'url'   : "CONCAT('/event/update/',id,'/')",
    })

    events = events.filter(DTSTART__range=(sd, ed))
#    print events
    
    revents = []
        
    for event in events:
        d = event.DURATION
        revent = (event.id, 
                  event.title, 
                  event.DTSTART.isoformat(), 
                  (event.DTSTART+datetime.timedelta(minutes=d.minute, hours=d.hour)).isoformat(), 
                  0, #IsAllDayEvent
                  0, #more than one day event
                  0, #Recurring event
                  event.id % 14, #Color
                  1, #editable
                   dict(event.MODE_CHOICES).get(event.mode,''), #Location 
                  '', #attends                  
                  )
        logging.info(revent)
        revents.append(revent)
        
    ret = {}
    ret['events'] = revents
    ret["issort"] = True
    ret["start"] = sd.isoformat()
    ret["end"] = ed.isoformat()
    ret['error'] = None
    
    return ret


def listCalendar(day, type):
    date = datetime.datetime.strptime(day, '%m/%d/%Y')
    logging.info(date)
    if type == 'month':
        st = date - datetime.timedelta(31)
        et = date + datetime.timedelta(31)
        cnt = 50
    elif type == 'week':
        st = date - datetime.timedelta(7)
        et = date + datetime.timedelta(7)
        cnt = 20
    elif type == 'day':
        st = date - datetime.timedelta(1)
        et = date + datetime.timedelta(1)
        cnt = 5
    
    return listCalendarByRange(st, et, cnt)

#@login_required
def datafeed(request):

    try:

    #    print request
        method = request.GET['method']
    #    print method
        
        if method == 'add':
            pass
        elif method == 'list':
            ret = listCalendar(request.POST['showdate'], request.POST['viewtype'])
        elif method == 'update':
            pass
        elif method == 'remove':
            pass
        elif method == 'adddetails':
            pass
        
    except:
        ret = listCalendar('8/3/2011', 'month')
        
    dumper = DataDumper()
    return HttpResponse(dumper.dump(ret,'json'))

# class VEVENT_ViewSet(viewsets.ModelViewSet):
class VEVENT_List(generics.ListAPIView):

    """
    API endpoint that allows groups to be viewed or edited.
    """
    # queryset = VEVENT.objects.all()
    serializer_class = VEVENT_Serializer

    def get_queryset(self):
        """
        Optionally restricts the returned purchases to a given user,
        by filtering against a `username` query parameter in the URL.
        """
        queryset = VEVENT.objects.all()
        queryset = VEVENT.objects.all()
        start = self.request.query_params.get('start', None)
        end   = self.request.query_params.get('end', None)
        if start is not None and end is not None:
            queryset = queryset.filter(DTSTART__range=(start, end)).filter(mode__gt=100)
        return queryset    




class NHIOrderList(ListView):
    model = NHIOrder
    paginate_by = 25

    # context_object_name = 'my_book_list'   # your own name for the list as a template variable
    # queryset = Book.objects.filter(title__icontains='war')[:5] # Get 5 books containing the title war
    # template_name = 'books/my_arbitrary_template_name_list.html'  # Specify your own template name/location

# class MyDatatable(Datatable):
#     model = NHIOrder
#     class Meta:
#         exclude = ['id', 'timestamp', 'updated']

# class NHIOrderDatatableView(DatatableView):
#     model = NHIOrder

#     datatable_class = MyDatatable

#  Args: (<NHIOrder: NHIOrder object (3938132_2020-08-27)>,)
#  Kwargs: {'default_value': '', 'rich_value': '', 'localize': False, 'datatable': <ck.views.datatable_class_Synthesized object at 0x7fb5ddb10730>, 'view': <ck.views.NHIOrderDatatableView object at 0x7fb5ddb39250>

# <a class="editable editable-click editable-empty" href="#" data-name="ApplyDoctor" data-pk="0950575_2020-12-23" data-placeholder="" data-source="/abcd" data-sourceoptions="{'data': {'param': 123}}" data-type="select" data-url="/pre-case/" data-value="" data-xeditable="xeditable">Empty</a>



# @cache
def AllDoctors(NhiDeptName):

    # if NhiDeptName == '放射腫瘤科':
    #     dr, count = zip(*list(Treatment.objects.values_list("oncologist__name").annotate(Count("id")).order_by('-id__count')))
    #     dr2 = Oncologist.objects.values_list('name', flat=True)
    # else:
    #     dr, count = zip(*list(Treatment.objects.values_list("surgeon__name").annotate(Count("id")).order_by('-id__count')))
    #     dr2 = Surgeon.objects.values_list('name', flat=True)  
    # return list(dr) + [d for d in list(dr2) if d not in dr]

    dr, count = zip(*list(Treatment.objects.values_list("oncologist__name").annotate(Count("id")).order_by('-id__count')))
    dr2 = Oncologist.objects.values_list('name', flat=True)
    onco = list(dr) + [d for d in list(dr2) if d not in dr]

    dr, count = zip(*list(Treatment.objects.values_list("surgeon__name").annotate(Count("id")).order_by('-id__count')))
    dr2 = Surgeon.objects.values_list('name', flat=True)
    surg = list(dr) + [d for d in list(dr2) if d not in dr]

    if NhiDeptName == '放射腫瘤科':
        return [d for d in onco+surg if d is not None]
    
    return [d for d in surg+onco if d is not None]
  

@cache
def DoctorOptionByChartNo(ChartNo,NhiDeptName):
    all = AllDoctors(NhiDeptName)

    # records = portal.PatientMedicalRecordListQuery(ChartNo)
    # records = records['Emergency']+records['InPat']+records['OutPat']
    # # print(records)

    # doctors = set()
    # for record in records:
    #     MainDrName = record['MainDrName']
    #     if MainDrName is not None:
    #         MainDrName = MainDrName.replace('\ue09b', '峰') #'許峰銘'
    #         doctors.add(MainDrName) 

    # # print(doctors)

    # # print(all)
    # # print(doctors)
    # intersect = [x for x in all if x in doctors]

    # if not intersect:
    #     intersect = all

    res = []

    for d in all:
        res.append({'value': d, 'text': d})                

    # res = [{'value': 1, 'text': "text1"}, {'value': 2, 'text': "text2"}]

    return JsonResponse(res, safe=False)


# [{value: 1, text: "text1"}, {value: 2, text: "text2"}, ...]
def DoctorOption(request):

    id = request.GET.get('id', '')
    data = NHIOrder.objects.get(id=id)
    return DoctorOptionByChartNo(data.ChartNo,data.NhiDeptName)

def GetDoctorByCode(code):
    # print(f'--{code}--')
    dr = Surgeon.objects.filter(staff_code=code).first()
    if dr:
        return dr
    dr = Oncologist.objects.filter(staff_code=code).first()
    if dr:
        return dr
    return None


class NHIOrderDatatableView(XEditableDatatableView):
    model = NHIOrder

    def filter_queryset(self, qs):
        print(123)

    def get_queryset(self):

        order = None

        ChartNo = self.request.GET.get('ChartNo')
        own = self.request.GET.get('own')
        if (ChartNo is not None) and len(ChartNo) > 1:
            if own is not None:
                PackageTime = datetime.datetime.today().strftime('%Y-%m-%d')
                id = ChartNo+'_'+PackageTime[:7]
                order = NHIOrder.objects.filter(id=id).first()

                if order is None:
                    pat = portal.QueryModifyPatBase({'ChartNo': ChartNo})
                    print(pat)
                    order = NHIOrder()
                    order.ChartNo     = ChartNo
                    order.PackageTime = datetime.datetime.today().strftime('%Y-%m-%d')
                    order.id          = order.ChartNo+'_'+order.PackageTime[:7]
                    order.PatientName = pat['ChtName']
                    order.ApplyTypeDesc = '自費'
                    order.Priority = 1
                    order.save()

        NHIOrder_id = self.request.GET.get('NHIOrder')
        if NHIOrder_id is not None:
            order = NHIOrder.objects.get(id=NHIOrder_id)

        if order is not None:
            dr = GetDoctorByCode(self.request.user.username)
            if dr is not None:
                order.ApplyDoctor = dr.name
                order.save()

        queryset = super().get_queryset()

        if self.request.user.is_staff:
            # if self.request.GET.get('search[value]')=="None":
            #     return NHIOrder.objects.filter(ApplyDoctor__isnull=True)
            return queryset

        # print(self.request.user)
        # print(self.request.user.is_staff)

        dr = GetDoctorByCode(self.request.user.username)
        # print(dr)
        if dr:
            return queryset.filter(ApplyDoctor=dr.name)


        return queryset.none()
        return queryset.filter(**self.request.GET.dict())


    def get_context_data(self, **kwargs):
        # Call the base implementation first to get a context
        context = super().get_context_data(**kwargs)
        # Add in the publisher
        # context['publisher'] = self.publisher

        qs = NHIOrder.objects.filter(Priority__gt=0)
        context['total'] = qs.count()
        # context['waiting_list'] = NHIOrder.objects.filter(Priority__gt=0).values('ApplyDoctor').annotate(count=Count('ApplyDoctor')).order_by('-count')
        context['waiting_list'] = qs.values('ApplyDoctor').annotate(count=Count('*')).order_by('-count')

 

        if self.request.GET.get('refresh') is not None:
            SortNHI(CheckTreated=False)


        # context['ChartNo'] = self.request.GET.get('ChartNo')
        NHIOrder_id = self.request.GET.get('NHIOrder')
        if NHIOrder_id:
            context['search'] = NHIOrder_id.split('_')[0]

        ChartNo = self.request.GET.get('ChartNo')
        if ChartNo:
            context['search'] = ChartNo

        return context

    class datatable_class(Datatable):

        # search for Empty ApplyDoctor
        def search(self, queryset):
            if 'None' in self.config['search']:
                return queryset.filter(ApplyDoctor__isnull=True,Priority__gt=0)
            return super().search(queryset)

        def ProcessQuantity(self, *args, **kwargs):
            # print(f' Args: {args}' )
            # print(f' Kwargs: {kwargs}' )

            data = args[0]

            default_value = kwargs['default_value']

            title = ''

            if data.Reason:
                title += data.Reason+'&#10;'

            if data.ExamineReasonDesc:
                title += data.ExamineReasonDesc

            if title:
                return f'{default_value}<i class="fa fa-info-circle" title="{title}"></i>'

            return f'{default_value}'


            if ExamineReasonDesc is None:
                # return f'{default_value}<span class="material-icons" title="{data.Reason}">info</span>'
                return f'{default_value}<i class="fa fa-info-circle" title="{data.Reason}"></i>'

            return f'{default_value}<i class="fa fa-info-circle" title="{data.ExamineReasonDesc}"></i>'

        def ProcessDiagnosis(self, *args, **kwargs):
            data = args[0]
            default_value = kwargs['default_value']
            title = ''

            # print(f'-{default_value}-')

            # if default_value:

            icd10 = ICD10CMfinal.objects.filter(ICD10CM=default_value).first()
            if icd10 is not None:
                title = icd10.ICD10CM_Chinese

            # return f'{default_value}<span class="glyphicon glyphicon-info-sign" title="{title}"></span>'
            return f'{default_value} {title}'


        PriorityStyle = {
            1: 'background:red',
            2: 'background:yellow',
            3: 'background:green',
            4: 'background:white',
            '': '',
        }

        def ProcessPriority(self, *args, **kwargs):
            data = args[0]
            default_value = kwargs['default_value']

            # if default_value== is None or :
            #     style = ""
            # else:
            style = PriorityStyle[default_value]

            # return '''
            # <a href="#" data-name="Priority" data-pk="%s" data-placeholder="" 
            # data-source="[{value: 1, text: '1'}, {value: 2, text: '2'}]" 
            # data-type="select" data-url="/pre-case/" data-value="1" data-xeditable="xeditable" class="editable editable-click" data-original-title="" title="">%s</a>
            # ''' % (data.id, default_value)

            # data-source="[{value: 1}, {value: 2}, {value: 3}, {value: 4}]" 

            return '''
            <a href="#" data-name="Priority" data-pk="%s" data-placeholder="" 
            data-source="[{value: 1, text: '1'}, {value: 2, text: '2'}, {value: 3, text: '3'}]" 
            data-type="select" data-url="/pre-case/" data-value="%s" data-xeditable="xeditable" class="editable editable-click" data-original-title="" title=""
            style="%s"
            >%s</a>
            ''' % (data.id, default_value, style, default_value)


        def ProcessChartNo(self, *args, **kwargs):
            data = args[0]
            default_value = kwargs['default_value']
            return f'''
            <a class="editable-click" href="{reverse('patient-search')}?q={default_value}">{default_value}</a>
            '''


        def ProcessPatientName(self, *args, **kwargs):
            data = args[0]
            default_value = kwargs['default_value']
            return f'''
            <a class="editable-click" href="{reverse('patient-search')}?q={data.ChartNo}">{default_value}</a>
            '''

        def DoctorSelect(self, *args, **kwargs):
            # print(f' Args: {args}' )
            # print(f' Kwargs: {kwargs}' )

            data = args[0]
            default_value = kwargs['default_value']

            # if default_value=="":
            #    default_value = "zzz" 

            # print('---',default_value,'---')

            # XEditableDatatableView will fix the css class and empty text later

            if kwargs['view'].request.user.is_staff:
                return '''
                <a href="#" data-name="ApplyDoctor" 
                data-pk="%s" data-placeholder="" data-source="/DoctorOption?id=%s" data-sourceCache="false"
                data-sourceoptions='{"data": {"id": "%s"}}' data-type="select" data-url="/pre-case/" data-value="%s" 
                data-xeditable="xeditable">%s</a>
                ''' % (data.id, data.id, data.id, default_value, default_value)
            else:
                return default_value

        class Meta:
            # exclude = ['id', 'timestamp', 'updated', '', '']


            columns = [
                'ChartNo',
                'PatientName',
                'ApplyTypeDesc',
                'StatusDesc',
                'PackageTime',
                'OrderCode',
                # 'OrderName',
                # 'ResultDesc',
                'Quantity',
                'ExamineQuantity',
                'ExamineDate',

                'Diagnosis',
                'other_diagnosis',
                'num_sessions',

                'NhiDeptName',
                'MainDrName',
                'ApplyDoctor',
                # 'ExamineReasonDesc',

                'Priority',
                'Memo',
            ]

            ordering = ['-Priority', 'PackageTime'] 

            processors = { 
                # 'ChartNo': 'ProcessChartNo', 
                # 'PatientName': ProcessPatientName, 
                'Quantity': 'ProcessQuantity', 
                'Diagnosis': 'ProcessDiagnosis',
                'other_diagnosis': helpers.make_xeditable(),
                'num_sessions': helpers.make_xeditable(),
                'ApplyDoctor': 'DoctorSelect', 

                # 'Priority': helpers.make_xeditable(type='select', 
                # source='[{value: 1, text: "1"}, {value: 2, text: "2"}, {value: 3, text: "3"}]'
                # ), 

                'Priority': helpers.make_xeditable(),
                'Memo': helpers.make_xeditable(),


            } 

            structure_template = "datatableview/bootstrap_structure.html"

def pre_add(request):
    ChartNo = request.GET.get('ChartNo')

    ### A little bit too slow?
    if False and (ChartNo is not None) and len(ChartNo) > 1:
        for case in portal.QueryCaseByChartNo(ChartNo):
            print(case)
            UpdateNHICase(case)

    nhiorders = NHIOrder.objects.filter(ChartNo=ChartNo)
    context = {
        'ChartNo': ChartNo,
        'nhiorders': nhiorders,
    }

    if not nhiorders:
        pat = portal.QueryModifyPatBase({'ChartNo': ChartNo,})

        context['pat']=pat

    template = loader.get_template('ck/nhiorder_add.html')
    return HttpResponse(template.render(context, request))

class LesionCreate(CreateView):
    # model = Lesion
    form_class = LesionForm
    template_name = 'ck/lesion_form.html'    

    # Need this to set treatment_id
    def form_valid(self, form):
        # lesion = form.save(commit=False)
        # lesion.treatment_id = self.kwargs.get('treatment_id')
        #article.save()  # This is redundant, see comments.
        form.instance.treatment_id = self.kwargs['treatment_id']
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["treatment"] = get_object_or_404(Treatment, pk=self.kwargs.get('treatment_id'))
        return context


class LesionUpdate(UpdateView):
    model = Lesion
    form_class = LesionForm

class LesionDelete(DeleteView):
    model = Lesion

    # success_url = reverse_lazy('treatment-detail')
    def get_success_url(self):
        # Assuming there is a ForeignKey from Comment to Post in your model
        return reverse_lazy( 'treatment-detail', kwargs={'object_id': self.object.treatment_id})    


def CalendarIndex(request):
    if request.GET.get('download') is not None:
        QueryMS()
    context={}
    return render(request, 'calendar/index.html', context)

