# -*- encoding: utf-8 -*-

from datetime import date, datetime, timedelta
from datetime import time as ttime
import time
import json
from itertools import chain
from decimal import Decimal

from django.contrib.auth.decorators import login_required
from django.utils.translation import ugettext as _
from django.utils import simplejson
from django.db.models import Q
from django.core.urlresolvers import reverse
from django.shortcuts import render_to_response, redirect, get_object_or_404
from django.forms.util import ErrorList
from django.db.models.query import QuerySet

from django.contrib.auth.models import User
from django.template import RequestContext

from django.conf import settings
from django.http import Http404
from django.http import HttpResponse
from django.http import HttpResponseRedirect

from decorators import paginate
from decorators import only_doctor
from decorators import only_doctor_administrative

from userprofile.models import Profile
from cal.models import Slot
from cal.models import SlotType
from cal.models import Appointment
from cal.models import Vacation
from cal.models import Event
from cal.models import Payment

from cal.forms import SlotForm
from cal.forms import SlotTypeForm
from cal.forms import DoctorSelectionForm
from cal.forms import AppointmentForm
from cal.forms import VacationForm
from cal.forms import EventForm
from cal.forms import SchedulerForm
from cal.forms import PaymentForm
from cal.forms import PaymentFiltersForm

from cal.utils import create_calendar
from cal.utils import add_minutes
from cal.utils import get_weekday
from cal.utils import mnames
from cal.utils import get_doctor_preferences
from cal.utils import check_vacations
from cal.utils import check_scheduled_apps

@login_required
@only_doctor_administrative
def index(request):
    if 'appointment' in request.session:
        del request.session['appointment']
    if 'illness' in request.session:
        del request.session['illness']

    return render_to_response("cal/main/index_cal.html", dict(year = time.localtime()[0],month = time.localtime()[1]),
        context_instance=RequestContext(request))

@login_required
@only_doctor_administrative
def main(request, year=None):
    if year:
        year = int(year)
    else:
        year = time.localtime()[0]

    nowy, nowm = time.localtime()[:2]
    lst = []

    for y in [year, year + 1, year + 2]:
        mlst = []
        for n, month in enumerate(mnames):
            slot = current = False
            slots = Slot.objects.filter(date__year=y, date__month=n + 1)

            if slots:
                slot = True
            if y == nowy and n + 1 == nowm:
                current = True
            mlst.append(dict(n=n + 1, name=month, slot=slot,
                current=current))
        lst.append((y, mlst))

    today = time.localtime()[2:3][0]

    data = dict(years=lst, user=request.user, year=year, today=today)

    return render_to_response("cal/app/main.html", data,
        context_instance=RequestContext(request))

@login_required
@only_doctor_administrative
def select_month_year(request, year=None):
    if year:
        year = int(year)
    else:
        year = time.localtime()[0]

    nowy, nowm = time.localtime()[:2]
    lst = []

    for y in [year, year + 1, year + 2]:
        mlst = []
        for n, month in enumerate(mnames):
            slot = current = False
            slots = Slot.objects.filter(year=y, month=n)

            if slots:
                slot = True
            if y == nowy and n + 1 == nowm:
                current = True
            mlst.append(dict(n=n + 1, name=month, slot=slot,
                current=current))
        lst.append((y, mlst))

    today = time.localtime()[2:3][0]

    data = dict(years=lst, user=request.user, year=year, today=today)

    return render_to_response("cal/app/select_month_year.html",
        data, context_instance=RequestContext(request))

@login_required
@only_doctor_administrative
def scheduler(request, id_patient, year=None):
    patient = get_object_or_404(User, pk=int(id_patient))
    if patient.get_profile().is_patient() and patient.get_profile().doctor is None:
        return HttpResponseRedirect(reverse('cal.select_doctor', args=[id_patient]))
    if year:
        year = int(year)
    else:
        year = time.localtime()[0]

    nowy, nowm = time.localtime()[:2]
    lst = []

    for y in [year, year + 1, year + 2]:
        mlst = []
        for n, month in enumerate(mnames):
            slot = current = False
            slots = Slot.objects.filter(year=y, month=n)

            if slots:
                slot = True
            if y == nowy and n + 1== nowm:
                current = True
            mlst.append(dict(n=n + 1, name=month, slot=slot,
                current=current))
        lst.append((y, mlst))

    today = time.localtime()[2:3][0]

    data = dict(years=lst, year=year, month=nowm, today=today,
            patient_user=patient, doctor=patient.get_profile().doctor)

    return render_to_response("cal/app/scheduler.html",
        data, context_instance=RequestContext(request))

@login_required
@only_doctor_administrative
def month(request, year, month, change=None):
    year, month = int(year), int(month)

    if change in ("next", "prev"):
        now, mdelta = date(year, month, 15), timedelta(days=31)

        if change == "next":
            mod = mdelta

        elif change == "prev":
            mod = -mdelta

        year, month = (now + mod).timetuple()[:2]

    if request.user.get_profile().is_doctor():
        lst = create_calendar(year, month, doctor=request.user)
        return render_to_response("cal/doctor/month.html",
            dict(year=year, month=month, user=request.user,
                month_days=lst, mname=mnames[month - 1]),
                context_instance=RequestContext(request))
    else:
        return redirect(reverse("cal.views.doctor_calendar",
            args=(int(year), int(month))))

@login_required
@only_doctor_administrative
@paginate(template_name='cal/doctor/list.html', list_name='events',
    objects_per_page=settings.OBJECTS_PER_PAGE)
def day(request, year, month, day, id_user, change=None):
    user = User.objects.get(pk=int(id_user))
    if user.get_profile().is_doctor():
        doctor = user
        patient = None
    else:
        doctor = user.get_profile().doctor
        patient = user

    if change in ("next", "prev"):
        now, mdelta = date(int(year), int(month), int(day)), timedelta(days=1)

        if change == "next":
            mod = mdelta

        elif change == "prev":
            mod = -mdelta

        year, month, day= (now + mod).timetuple()[:3]

    events = Appointment.objects.filter(date__year=year, date__month=month,
            date__day=day, doctor=doctor).order_by('start_time')
    vacations = check_vacations(doctor, year, month, day)
    lst = create_calendar(int(year), int(month), doctor=doctor)
    doctor_preferences = get_doctor_preferences(year=year, month=month,
                day=day, doctor=doctor.id)

    available, free_intervals = Appointment.objects.availability(
                doctor,
                date(int(year), int(month), int(day)))

    template_data = dict(year=year, month=month, day=day, vacations=vacations,
        doctor=doctor, month_days=lst, mname=mnames[int(month) - 1],
        events=events, free_intervals=free_intervals,
        patient_user=patient, doctor_preferences=doctor_preferences,
        birthdays=Profile.objects.filter(dob__month=month, dob__day=day),
        context_instance=RequestContext(request))

    return template_data

@login_required
@only_doctor_administrative
def calendar(request, year, month, day, id_user, change='this'):

    if change in ("next", "prev"):
        now, mdelta = date(int(year), int(month), 15), timedelta(days=31)

        if change == "next":
            mod = mdelta

        elif change == "prev":
            mod = -mdelta

        year, month = (now + mod).timetuple()[:2]

    user = User.objects.get(pk=int(id_user))
    if user.get_profile().is_doctor():
        doctor = user
        patient = None
    else:
        doctor = user.get_profile().doctor
        patient = user
    lst = create_calendar(int(year), int(month), doctor=doctor)
    if int(day):
        available, free_intervals = Appointment.objects.availability(doctor,
                date(int(year), int(month), int(day)))
        doctor_preferences = get_doctor_preferences(year=year, month=month,
                day=day, doctor=doctor.id)
    else:
        available, free_intervals, doctor_preferences = [],[],[]

    return render_to_response('cal/includes/calendar.html',
                                dict(year=year, month=month, day=day,
                                 doctor=doctor, month_days=lst,
                                 patient_user=patient,
                                 mname=mnames[int(month) - 1],
                                 free_intervals=free_intervals,
                                 doctor_preferences=doctor_preferences),
        context_instance=RequestContext(request))

@login_required
@only_doctor_administrative
def calendar_big(request, year, month, change='this', id_doctor=None):

    if change in ("next", "prev"):
        now, mdelta = date(int(year), int(month), 15), timedelta(days=31)

        if change == "next":
            mod = mdelta

        elif change == "prev":
            mod = -mdelta

        year, month = (now + mod).timetuple()[:2]

    doctors = Profile.objects.filter(role=settings.DOCTOR)
    if id_doctor:
        doctor = User.objects.get(pk=int(id_doctor))
        lst = create_calendar(int(year), int(month), doctor=doctor)
    else:
        doctor = None
        lst = create_calendar(int(year), int(month), doctor=request.user)
        if request.user.get_profile().is_administrative():
            for d in doctors:
                dlst = create_calendar(int(year), int(month), doctor=d.user)
                for i in range(len(lst)):
                    for j in range(len(lst[i])):
                        for k in range(len(lst[i][j])):
                            if isinstance(lst[i][j][k], list) and isinstance(dlst[i][j][k], list):
                                lst[i][j][k] += dlst[i][j][k]

    form = DoctorSelectionForm()

    return render_to_response('cal/includes/calendar_big.html',
                                dict(year=year, month=month, doctors=doctors,
                                 doctor=doctor, month_days=lst,
                                 mname=mnames[int(month) - 1], form = form),
        context_instance=RequestContext(request))

@login_required
@only_doctor_administrative
@paginate(template_name='cal/doctor/list_consultation.html',
    list_name='events', objects_per_page=settings.OBJECTS_PER_PAGE)
def day_consultation(request, year, month, day):
    events = Appointment.objects.filter(date__year=year, date__month=month,
            date__day=day, doctor=request.user).order_by('start_time')

    lst = create_calendar(int(year), int(month), doctor=request.user)

    available, free_intervals = Appointment.objects.availability(
                request.user,
                date(int(year), int(month), int(day)))

    template_data = dict(year=year, month=month, day=day,
        user=request.user, month_days=lst, mname=mnames[int(month) - 1],
        events=events, free_intervals=free_intervals,
        birthdays=Profile.objects.filter(dob__month=month, dob__day=day),
        context_instance=RequestContext(request))

    return template_data

@login_required
@only_doctor_administrative
def app_add(request, year, month, day, id_user, check=False):
    user = User.objects.get(pk=int(id_user))
    if user.get_profile().is_doctor():
        doctor = user
        patient = None
    else:
        doctor = user.get_profile().doctor
        patient = user

    lst = create_calendar(int(year), int(month), doctor=doctor)
    vacations = check_vacations(doctor, year, month, day)

    if vacations:
        return render_to_response("cal/app/edit.html",
                {'vacations': vacations,
                 'year': int(year), 'month': int(month), 'day': int(day),
                 'month_days': lst,
                 'doctor': doctor,
                 'patient_user': patient,
                 'not_available_error': True,
                 'error_msg': _('Appointment can not be set. '\
                    'Please, choose another time interval')},
                context_instance=RequestContext(request))

    mname = mnames[int(month) - 1]

    doctor_preferences = get_doctor_preferences(year=year, month=month,
        day=day, doctor=doctor.id)

    if request.method == 'POST':
        sched_form = SchedulerForm(request.POST)
        request_params = dict([k, v] for k, v in request.POST.items())
        request_params.update({
            'doctor': doctor.id,
            'created_by': request.user.id,
            'date': date(int(year), int(month), int(day)),
            'patient': patient.id # WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        })

        id_app_type = request.POST.get('app_type', None)
        start_time = request.POST.get('start_time', None)
        end_time = request.POST.get('end_time', None)

        if id_app_type:
            app_type = get_object_or_404(SlotType, pk=int(id_app_type))
            duration = app_type.duration
            request_params.update({'app_type': app_type.id})

            if end_time:
                end_time = time.strptime(end_time, '%H:%M')
                end_time = ttime(end_time[3], end_time[4], end_time[5])

                if start_time:
                    start_time = time.strptime(start_time, '%H:%M')
                    start_time = ttime(start_time[3], start_time[4], start_time[5])
                    duration = ((datetime.combine(date.today(), end_time) - \
                        datetime.combine(date.today(), start_time)).seconds) / 60
                    #del request_params['app_type']
            else:
                if start_time:
                    start_time = time.strptime(start_time, '%H:%M')
                    end_time = add_minutes(start_time, duration)
                    start_time = ttime(start_time[3], start_time[4], start_time[5])

            request_params.update({'start_time': start_time,
                    'end_time': end_time, 'duration': duration})
        else:
            if start_time and end_time:
                start_time = time.strptime(start_time, '%H:%M')
                start_time = ttime(start_time[3], start_time[4], start_time[5])

                end_time = time.strptime(end_time, '%H:%M')
                end_time = ttime(end_time[3], end_time[4], end_time[5])

                duration = (datetime.combine(date.today(), end_time) - \
                    datetime.combine(date.today(), start_time)).seconds

                request_params.update({'start_time': start_time,
                    'end_time': end_time, 'duration': duration / 60})

        form = AppointmentForm(request_params, user=doctor)

        if form.is_valid() and sched_form.is_valid():
            pre_save_instance = form.save(commit=False)
            available, free_intervals = Appointment.objects.availability(
                doctor,
                date(int(year), int(month), int(day)),
                pre_save_instance)

            if available and not check:
                form.save()
                if sched_form.is_valid():
                    number = sched_form.cleaned_data['number']
                    period = sched_form.cleaned_data['period']
                    interval = sched_form.cleaned_data['interval']
                    if number and period:
                        ok, conflicts = check_scheduled_apps(pre_save_instance, number, period, interval)
                        for app in ok:
                            app.pk = None
                            app.status = settings.RESERVED
                            app.save()

                if 'appointment' in request.session:
                    return redirect(reverse("consulting_main",
                        kwargs={'id_appointment':request.session['appointment'].id,
                            'code_illness':request.session['illness'].code}))
                else:
                    return redirect(reverse("cal.views.day",
                        args=(int(year), int(month), int(day), doctor.id)))
            else:
                error = False
                success = False
                conflicts = []
                msg = ''
                if not available:
                    error = True
                    msg = _(u'Conflicto de fecha y hora con otra cita. '\
                        'Por favor, seleccione un intervalo libre')
                elif sched_form.is_valid():
                    number = sched_form.cleaned_data['number']
                    period = sched_form.cleaned_data['period']
                    interval = sched_form.cleaned_data['interval']
                    if number and period:
                        ok, conflicts = check_scheduled_apps(pre_save_instance, number, period, interval)
                        if conflicts:
                            error = True
                            msg = _(u'La reserva de las siguientes citas presentan conflictos de disponibilidad en su agenda y no se crearán automáticamente' )
                        else:
                            msg = _(u'Es posible efectuar la reserva de las citas solicitadas' )
                            error = False
                            success = True

                return render_to_response("cal/app/add.html",
                    {'form': form,
                     'scheduler': sched_form,
                     'year': int(year), 'month': int(month), 'day': int(day),
                     'month_days': lst,
                     'mname': mname,
                     'doctor': doctor,
                     'patient_user': patient,
                     'conflicts': conflicts,
                     'doctor_preferences': doctor_preferences,
                     'free_intervals': free_intervals,
                     'not_available_error': error,
                     'successful_check': success,
                     'error_msg': msg},
                    context_instance=RequestContext(request))
        else:
            available, free_intervals = Appointment.objects.availability(
                doctor,
                date(int(year), int(month), int(day)))
    else:
        app_type = request.GET.get('type','')
        sched_form = SchedulerForm()
        form = AppointmentForm(user=doctor, initial={'app_type': app_type})
        available, free_intervals = Appointment.objects.availability(
            doctor,
            date(int(year), int(month), int(day)))
    if date(int(year), int(month), int(day)) < date.today():
        form = None

    return render_to_response("cal/app/add.html",
                {'form': form,
                 'scheduler': sched_form,
                 'year': int(year), 'month': int(month), 'day': int(day),
                 'month_days': lst,
                 'mname': mname,
                 'doctor': doctor,
                 'patient_user': patient,
                 'doctor_preferences': doctor_preferences,
                 'free_intervals': free_intervals},
                context_instance=RequestContext(request))

@login_required
@only_doctor_administrative
def app_edit(request, pk):
    app = get_object_or_404(Appointment, pk=int(pk))
    if not app.is_editable():
        raise Http404

    patient = app.patient
    doctor = app.doctor

    year = int(app.date.year)
    month = int(app.date.month)
    day = int(app.date.day)

    mname = mnames[int(month) - 1]

    lst = create_calendar(year, month, doctor=doctor)

    vacations = check_vacations(doctor, year, month, day)
    available, free_intervals = Appointment.objects.availability(
            doctor,
            date(int(year), int(month), int(day)))

    doctor_preferences = get_doctor_preferences(year=year, month=month,
        day=day, doctor=doctor.id)

    if request.method == 'POST':
        request_params = dict([k, v] for k, v in request.POST.items())
        request_params.update({
            'doctor': doctor.id,
            'created_by': request.user.id,
            'patient': patient.id # WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        })

        start_time = request.POST.get('start_time', None)
        end_time = request.POST.get('end_time', None)
        app_type = request.POST.get('app_type', None)

        if not app_type is None and not app_type == '':
            app_type = get_object_or_404(SlotType, pk=int(app_type))

            duration = app_type.duration
            request_params.update({'app_type': app_type.id})

            if end_time:
                end_time = time.strptime(end_time, '%H:%M')
                end_time = ttime(end_time[3], end_time[4], end_time[5])

                if start_time:
                    start_time = time.strptime(start_time, '%H:%M')
                    start_time = ttime(start_time[3], start_time[4], start_time[5])
                    duration = (datetime.combine(date.today(), end_time) - \
                        datetime.combine(date.today(), start_time)).seconds / 60
                    #del request_params['app_type']
            else:
                if start_time:
                    start_time = time.strptime(start_time, '%H:%M')
                    end_time = add_minutes(start_time, duration)
                    start_time = ttime(start_time[3], start_time[4], start_time[5])

            request_params.update({'start_time': start_time,
                    'end_time': end_time, 'duration': duration})
        else:
            if end_time:
                end_time = time.strptime(end_time, '%H:%M')
                end_time = ttime(end_time[3], end_time[4], end_time[5])

                if start_time:
                    start_time = time.strptime(start_time, '%H:%M')
                    start_time = ttime(start_time[3], start_time[4], start_time[5])

                    duration = datetime.combine(date.today(), end_time) - \
                        datetime.combine(date.today(), start_time)
                    request_params.update({'end_time': end_time,
                        'start_time': start_time,
                        'duration': duration.seconds / 60})

        selected_date = date(int(year), int(month), int(day))
        request_params.update({'weekday': get_weekday(selected_date)})

        form = AppointmentForm(request_params, instance=app, user=doctor)

        if form.is_valid():
            pre_edit_instance = form.save(commit=False)
            year = int(pre_edit_instance.date.year)
            month = int(pre_edit_instance.date.month)
            day = int(pre_edit_instance.date.day)

            mname = mnames[int(month) - 1]

            lst = create_calendar(year, month, doctor=doctor)

            vacations = check_vacations(doctor, year, month, day)

            doctor_preferences = get_doctor_preferences(year=year, month=month,
                day=day, doctor=doctor.id)

            if vacations:
                return render_to_response("cal/app/edit.html",
                        {'form': form,
                         'event': app,
                         'year': year, 'month': month, 'day': day,
                         'month_days': lst,
                         'mname': mname,
                         'doctor': doctor,
                         'patient_user': patient,
                         'doctor_preferences': doctor_preferences,
                         'free_intervals': free_intervals,
                                'vacations': vacations},
                        context_instance=RequestContext(request))

            available, free_intervals = Appointment.objects.availability(
            doctor,
            date(int(year), int(month), int(day)),
            pre_edit_instance,
            edit=True)

            if available:
                form.save()

                if not request.user.get_profile().is_doctor():
                    return redirect(reverse("doctor_day",
                        args=(doctor.id, year, month, day)))
                else:
                    return redirect(reverse("cal.views.day",
                        args=(year, month, day, doctor.id)))
            else:
                return render_to_response("cal/app/edit.html",
                {'form': form,
                 'event': app,
                 'year': year, 'month': month, 'day': day,
                 'month_days': lst,
                 'mname': mname,
                 'doctor': doctor,
                 'patient_user': patient,
                 'doctor_preferences': doctor_preferences,
                 'free_intervals': free_intervals,
                 'not_available_error': True,
                 'error_msg': _('No se pudo crear la cita. '\
                    'Por favor, seleccione un intervalo de tiempo disponible')},
                context_instance=RequestContext(request))

        else:
            available, free_intervals = Appointment.objects.availability(
                doctor,
                date(int(year), int(month), int(day)))
    else:
        form = AppointmentForm(instance=app, user=doctor)
        available, free_intervals = Appointment.objects.availability(
            doctor,
            date(int(year), int(month), int(day)))

    return render_to_response("cal/app/edit.html",
        {'form': form,
         'event': app,
         'year': year, 'month': month, 'day': day,
         'month_days': lst,
         'mname': mname,
         'doctor': doctor,
         'patient_user': patient,
         'doctor_preferences': doctor_preferences,
         'free_intervals': free_intervals},
        context_instance=RequestContext(request))

@login_required
@only_doctor_administrative
def app_delete(request, pk):
    if request.method == 'DELETE':
        data = json.loads(request.raw_post_data)
        app_id = data['app_id']
        if int(app_id) != int(pk):
            raise Exception

        event = get_object_or_404(Appointment, pk=int(app_id))
        event.delete()

        try:
            return HttpResponse(json.dumps({'action': True}),
                status=200,
                mimetype='application/json')
        except:
            return HttpResponse(json.dumps({'action': False}),
                status=200,
                mimetype='application/json')
    else:
        return HttpResponse(json.dumps({'action': False}),
                status=200,
                mimetype='application/json')

@login_required
@only_doctor_administrative
@paginate(template_name='cal/patient/list.html',
    list_name='events', objects_per_page=settings.OBJECTS_PER_PAGE)
def app_list_patient(request, id_patient):
    patient = get_object_or_404(User, pk=int(id_patient))
    events = Appointment.objects.filter(patient=patient).order_by('-date')

    template_data = dict(events=events, doctor=patient.get_profile().doctor,
                        patient=patient,
                        context_instance=RequestContext(request))

    return template_data

@login_required()
@only_doctor_administrative
@paginate(template_name='cal/patient/list.html',
    list_name='events', objects_per_page=settings.OBJECTS_PER_PAGE)
def get_appointments(request, year, month, day):
    logged_user_profile = request.user.get_profile()

    #patient_user_id = request.session['patient_user_id']

    appointments = Appointment.objects.filter(date__year=int(year), date__month=int(month), date__day=int(day)).order_by('-start_time')

    template_data = {}
    template_data.update({'events': appointments})
    return template_data

@login_required
@only_doctor
@paginate(template_name='cal/slot_type/list.html',
    list_name='slot_type', objects_per_page=settings.OBJECTS_PER_PAGE)
def list_slot_type(request):
    slot_type = SlotType.objects.filter(doctor=request.user)

    template_data = dict(user=request.user, slot_type=slot_type,
        context_instance=RequestContext(request))

    return template_data

@login_required
@only_doctor
def add_slot_type(request, template="cal/slot_type/add.html"):
    if request.method == 'POST':
        request_params = dict([k, v] for k, v in request.POST.items())
        request_params.update({
            'doctor': request.user.id,
            'created_by': request.user.id,
        })

        form = SlotTypeForm(request_params)

        if form.is_valid():
            slot_type = form.save()
            to_url = request.GET.get('next',reverse("cal.list_slot_type"))
            return redirect(to_url+'?type='+str(slot_type.id))
        else:
            return render_to_response(template,
                {'form': form},
                context_instance=RequestContext(request))
    else:
        form = SlotTypeForm()

    return render_to_response(template, {'form': form},
                context_instance=RequestContext(request))

@login_required
@only_doctor
def edit_slot_type(request, pk, template="cal/slot_type/edit.html"):
    slot = get_object_or_404(SlotType, pk=int(pk))

    if request.method == 'POST':
        request_params = dict([k, v] for k, v in request.POST.items())
        request_params.update({
            'doctor': request.user.id,
            'created_by': request.user.id
        })

        form = SlotTypeForm(request_params, instance=slot)

        if form.is_valid():
            form.save()
            return redirect(reverse("cal.list_slot_type"))
        else:
            return render_to_response(template,
                {"form": form, 'slot_type': slot},
                context_instance=RequestContext(request))
    else:
        form = SlotTypeForm(instance=slot)

    return render_to_response(template,
        {"form": form, 'slot_type': slot},
        context_instance=RequestContext(request))

@login_required
@only_doctor
def delete_slot_type(request):
    if request.method == 'DELETE':
        data = json.loads(request.raw_post_data)
        pk = data['pk']

        slot_type = get_object_or_404(SlotType, pk=int(pk))

        try:
            slot_type.delete()
            return HttpResponse(json.dumps({'action': True}),
                status=200,
                mimetype='application/json')
        except:
            return HttpResponse(json.dumps({'action': False}),
                status=200,
                mimetype='application/json')
    else:
        return HttpResponse(json.dumps({'action': False}),
                status=200,
                mimetype='application/json')

@login_required
@only_doctor
def list_slot(request, year=None):
    if not year:
        year = time.localtime()[0]
    slots = Slot.objects.filter(creator=request.user, year=int(year))

    return render_to_response('cal/slot/list.html',
        dict(slots=slots, year=int(year)),
        context_instance=RequestContext(request))

@login_required
@only_doctor
def add_slot(request, year, month=1):
    if request.method == 'POST':
        start_time = request.POST.get('start_time', None)
        end_time = request.POST.get('end_time', None)
        id_slot_type = request.POST.get('slot_type', None)
        months = request.POST.getlist('months')
        weekdays = request.POST.getlist('weekdays')

        request_params = dict([k, v] for k, v in request.POST.items())
        request_params.update({
            'months': months,
            'weekdays': weekdays,
            })

        if id_slot_type:
            slot_type = get_object_or_404(SlotType, pk=int(id_slot_type))
            if start_time and not end_time:
                st = time.strptime(start_time, '%H:%M')
                end_time = add_minutes(st, slot_type.duration)

        form = SlotForm(request_params, user=request.user)

        if form.is_valid():
            for m in months:
                for d in weekdays:
                    s = Slot()
                    s.weekday = d
                    s.month = m
                    s.year = int(year)
                    s.start_time = start_time
                    s.end_time = end_time
                    s.creator = request.user
                    s.created_by = request.user
                    s.description = form.cleaned_data['description']
                    s.slot_type = slot_type
                    s.save()
            return redirect(reverse("cal.list_slot", args=(int(year),
                )))
        else:
            return render_to_response('cal/slot/add.html',
                {'form': form, 'year': year,},
                context_instance=RequestContext(request))
    else:
        slot_type = request.GET.get('type','')
        form = SlotForm(user=request.user,initial={'slot_type':slot_type})
        #form.fields['app_type'].initial = [slot_type]

    return render_to_response('cal/slot/add.html', {'form': form,
        'year': year,},
        context_instance=RequestContext(request))

@login_required
@only_doctor
def edit_slot(request, pk):
    slot = get_object_or_404(Slot, pk=int(pk))

    if request.method == 'POST':
        start_time = request.POST.get('start_time', None)
        end_time = request.POST.get('end_time', None)
        id_slot_type = request.POST.get('slot_type', None)
        months = request.POST.get('months')
        weekdays = request.POST.get('weekdays')

        request_params = dict([k, v] for k, v in request.POST.items())
        request_params.update({
            'months': months,
            'weekdays': weekdays,
            })
        slot_type = get_object_or_404(SlotType, pk=int(id_slot_type))

        if id_slot_type and start_time and not end_time:
            st = time.strptime(start_time, '%H:%M')
            end_time = add_minutes(st, slot_type.duration)

        form = SlotForm(request_params, user=request.user, slot=slot)

        if form.is_valid():
            s = slot
            s.weekday = weekdays
            s.month = months
            s.start_time = start_time
            s.end_time = end_time
            s.creator = request.user
            s.created_by = request.user
            s.description = form.cleaned_data['description']
            s.slot_type = slot_type
            s.save()
            return redirect(reverse("cal.list_slot", args=(slot.year,
                )))
        else:
            return render_to_response('cal/slot/edit.html',
                {"form": form, 'slot': slot,
                 'year': slot.year, 'month': slot.month},
                context_instance=RequestContext(request))
    else:
        form = SlotForm( dict(weekdays=[slot.weekday], months=[slot.month], start_time=slot.start_time, end_time=slot.end_time, slot_type=slot.slot_type), user=request.user, slot=slot)

    return render_to_response('cal/slot/edit.html',
        {"form": form, 'slot': slot, 'year': slot.year,
         'month': slot.month},
        context_instance=RequestContext(request))

@login_required
@only_doctor
def delete_slot(request, pk):
    slot = get_object_or_404(Slot, pk=int(pk))
    year = int(slot.year)
    slot.delete()
    return redirect(reverse("cal.list_slot", args=(year,)))

@login_required
@only_doctor_administrative
def doctor_calendar(request):
    if request.method == 'POST':
        form = DoctorSelectionForm(request.POST)
        if form.is_valid():

            id_doctor = form.cleaned_data['doctor']

            return redirect(reverse("cal.scheduler",
                args=[int(id_doctor),]))
    else:
        form = DoctorSelectionForm()

    return render_to_response('cal/app/admin.html', {'form': form},
        context_instance=RequestContext(request))

@login_required
@only_doctor_administrative
def doctor_month(request, year, month, id_doctor, change=None):
    year, month = int(year), int(month)

    doctor = get_object_or_404(User, pk=int(id_doctor))
    if not doctor.get_profile().is_doctor():
        raise Http404

    if change in ("next", "prev"):
        now, mdelta = date(year, month, 15), timedelta(days=31)

        if change == "next":
            mod = mdelta

        elif change == "prev":
            mod = -mdelta

        year, month = (now + mod).timetuple()[:2]

    lst = create_calendar(year, month, doctor=doctor)
    doctor_preferences = get_doctor_preferences(year=year, month=month,
        doctor=id_doctor)

    return render_to_response("cal/app/month.html",
        dict(year=year, month=month, user=request.user, doctor=doctor,
            month_days=lst, mname=mnames[month - 1],
            doctor_preferences=doctor_preferences),
            context_instance=RequestContext(request))

@login_required
@only_doctor_administrative
@paginate(template_name='cal/app/list.html',
    list_name='events', objects_per_page=settings.OBJECTS_PER_PAGE)
def doctor_day(request, id_doctor, year, month, day):
    doctor = get_object_or_404(User, pk=int(id_doctor))
    if not doctor.get_profile().is_doctor():
        raise Http404

    vacations = check_vacations(doctor, year, month, day)

    if not vacations:
        events = Appointment.objects.filter(doctor=doctor, date__year=year,
            date__month=month, date__day=day).order_by('start_time')
    else:
        events = Appointment.objects.none()

    lst = create_calendar(int(year), int(month), doctor=doctor)
    doctor_preferences = get_doctor_preferences(year=year, month=month,
        day=day, doctor=id_doctor)

    available, free_intervals = Appointment.objects.availability(
                doctor,
                date(int(year), int(month), int(day)))

    template_data = dict(year=year, month=month, day=day, user=request.user,
        doctor=doctor, month_days=lst, mname=mnames[int(month) - 1],
        events=events, doctor_preferences=doctor_preferences,
        vacations=vacations, free_intervals=free_intervals,
        context_instance=RequestContext(request))

    return template_data

@login_required
@only_doctor
@paginate(template_name='cal/vacation/list.html',
    list_name='vacations', objects_per_page=settings.OBJECTS_PER_PAGE)
def list_vacation(request):
    vacations = Vacation.objects.filter(doctor=request.user).order_by('-date')
    years = vacations.dates('date','year',order='ASC')
    year = request.GET.get('year', '')
    if year:
        vacations = vacations.filter(date__year=year)

    queries_without_page = request.GET.copy()
    if queries_without_page.has_key('page'):
        del queries_without_page['page']

    template_data = dict(user=request.user, vacations=vacations, year=year,
                        queries=queries_without_page, years=years,
                        context_instance=RequestContext(request))

    return template_data

@login_required
@only_doctor
def add_vacation(request, template="cal/vacation/add.html"):
    if request.method == 'POST':
        start_date = request.POST.get('date', None)
        end_date = request.POST.get('end_date', start_date)
        if not end_date:
            end_date = start_date
        error = None
        request_params = dict([k, v] for k, v in request.POST.items())
        request_params.update({
            'doctor': request.user.id,
            'created_by': request.user.id,
            'date': start_date
        })
        form = VacationForm(request_params)
        form.is_valid()
        start_date = datetime.strptime(start_date, settings.DATE_INPUT_FORMAT)
        end_date = datetime.strptime(end_date, settings.DATE_INPUT_FORMAT)
        if end_date and end_date >= start_date:
            for n in range(int((end_date - start_date).days)+1):
                if Appointment.objects.filter(doctor=request.user, date=(start_date + timedelta(n))).count():
                    form._errors['__all__'] = ErrorList([u"Existen citas concertadas en el intervalo de vacaciones. Elija otro intervalo de fechas o modifique las citas concertadas."])
                    error = True
                    break
        else:
            form._errors['end_date'] = ErrorList([u"Fecha final debe ser mayor que la fecha inicial"])
            error = True

        if not error:
            for n in range(int((end_date - start_date).days)+1):
                request_params.update({
                    'date': (start_date + timedelta(n)).strftime(settings.DATE_INPUT_FORMAT)
                })

                form = VacationForm(request_params)

                if form.is_valid():
                    form.save()
                else:
                     return render_to_response(template,
                        {'form': form},
                        context_instance=RequestContext(request))
            return redirect(reverse("cal.list_vacation"))
        else:
            return render_to_response(template,
                {'form': form},
                context_instance=RequestContext(request))
    else:
        form = VacationForm()

    return render_to_response(template, {'form': form},
                context_instance=RequestContext(request))

@login_required
@only_doctor
def edit_vacation(request, pk, template="cal/vacation/edit.html"):
    vacation = get_object_or_404(Vacation, pk=int(pk))

    if request.method == 'POST':
        request_params = dict([k, v] for k, v in request.POST.items())
        request_params.update({
            'doctor': request.user.id,
            'created_by': request.user.id,
        })

        date = request.POST.get('date', None)
        if date:
            date = datetime.now().strptime(date, settings.DATE_INPUT_FORMAT)
            request_params.update({'date': date})

        form = VacationForm(request_params, instance=vacation)

        if form.is_valid():
            form.save()
            return redirect(reverse("cal.list_vacation"))
        else:
            return render_to_response(template,
                {"form": form, 'vacation': vacation},
                context_instance=RequestContext(request))
    else:
        form = VacationForm(instance=vacation)

    return render_to_response(template,
        {"form": form, 'vacation': vacation},
        context_instance=RequestContext(request))

@login_required
@only_doctor
def delete_vacation(request):
    if request.method == 'DELETE':
        data = json.loads(request.raw_post_data)
        pk = data['pk']

        vacation = get_object_or_404(Vacation, pk=int(pk))

        try:
            vacation.delete()
            return HttpResponse(json.dumps({'action': True}),
                status=200,
                mimetype='application/json')
        except:
            return HttpResponse(json.dumps({'action': False}),
                status=200,
                mimetype='application/json')
    else:
        return HttpResponse(json.dumps({'action': False}),
                status=200,
                mimetype='application/json')

@login_required
@only_doctor
@paginate(template_name='cal/event/list.html',
    list_name='events', objects_per_page=settings.OBJECTS_PER_PAGE)
def list_event(request):
    events = Event.objects.filter(doctor=request.user).order_by('-date')
    years = events.dates('date','year',order='ASC')
    year = request.GET.get('year', '')
    if year:
        events = events.filter(date__year=year)

    queries_without_page = request.GET.copy()
    if queries_without_page.has_key('page'):
        del queries_without_page['page']

    template_data = dict(user=request.user, events=events, year=year,
                        queries=queries_without_page, years=years,
                        context_instance=RequestContext(request))

    return template_data

@login_required
@only_doctor
def add_event(request, template="cal/event/add.html"):
    if request.method == 'POST':
        request_params = dict([k, v] for k, v in request.POST.items())
        request_params.update({
            'doctor': request.user.id,
            'created_by': request.user.id,
            'date': datetime.now()
        })

        date = request.POST.get('date', None)
        if date:
            date = datetime.now().strptime(date, settings.DATE_INPUT_FORMAT)
            request_params.update({'date': date})

        form = EventForm(request_params)

        if form.is_valid():
            form.save()
            return redirect(reverse("cal.list_event"))
        else:
            return render_to_response(template,
                {'form': form},
                context_instance=RequestContext(request))
    else:
        form = EventForm()

    return render_to_response(template, {'form': form},
                context_instance=RequestContext(request))

@login_required
@only_doctor
def edit_event(request, pk, template="cal/event/edit.html"):
    event = get_object_or_404(Event, pk=int(pk))

    if request.method == 'POST':
        request_params = dict([k, v] for k, v in request.POST.items())
        request_params.update({
            'doctor': request.user.id,
            'created_by': request.user.id,
        })

        date = request.POST.get('date', None)
        if date:
            date = datetime.now().strptime(date, settings.DATE_INPUT_FORMAT)
            request_params.update({'date': date})

        form = EventForm(request_params, instance=event)

        if form.is_valid():
            form.save()
            return redirect(reverse("cal.list_event"))
        else:
            return render_to_response(template,
                {"form": form, 'event': event},
                context_instance=RequestContext(request))
    else:
        form = EventForm(instance=event)

    return render_to_response(template,
        {"form": form, 'event': event},
        context_instance=RequestContext(request))

@login_required
@only_doctor
def delete_event(request):
    if request.method == 'DELETE':
        data = json.loads(request.raw_post_data)
        pk = data['pk']

        event = get_object_or_404(Event, pk=int(pk))

        try:
            event.delete()
            return HttpResponse(json.dumps({'action': True}),
                status=200,
                mimetype='application/json')
        except:
            return HttpResponse(json.dumps({'action': False}),
                status=200,
                mimetype='application/json')
    else:
        return HttpResponse(json.dumps({'action': False}),
                status=200,
                mimetype='application/json')

@login_required()
@only_doctor_administrative
def lookfor_patient(request, action=None, year=None, month=None, day=None):
    if action == 'info':
        pass
    elif action == 'new_app':
        if year and month and day:
            destination = 'cal.add'
        else:
            destination = 'cal.scheduler'
    elif action == 'list_app':
        destination = 'cal.app_list_patient'

    return render_to_response('cal/patient/lookfor_patient.html',
            {'destination':destination, 'year':year, 'month':month, 'day':day},
            context_instance=RequestContext(request))

@login_required()
@only_doctor_administrative
def patient_searcher(request):
    logged_user_profile = request.user.get_profile()

    if logged_user_profile.is_administrative() or\
        logged_user_profile.is_doctor():
        data = {'ok': False}
        if request.method == 'POST':
            start = request.POST.get("start", "")

            if logged_user_profile.is_administrative():
                profiles = Profile.objects.filter(
                                Q(role__exact=settings.PATIENT),
                                Q(nif__istartswith=start)|
                                Q(name__istartswith=start)|
                                Q(first_surname__istartswith=start)|
                                Q(second_surname__istartswith=start)).order_by(
                                'name', 'first_surname', 'second_surname')
            else:
                doctor_user = logged_user_profile.user
                profiles = Profile.objects.filter(
                                Q(doctor=doctor_user,
                                role__exact=settings.PATIENT),
                                Q(nif__istartswith=start)|
                                Q(name__istartswith=start)|
                                Q(first_surname__istartswith=start)|
                                Q(second_surname__istartswith=start)).order_by(
                                'name', 'first_surname', 'second_surname')

            data = {'ok': True,
                    'completed_names':
                    [{'id': profile.user.id,
                    'label':
                    (profile.get_full_name()+ ' ['+profile.nif+']')}for profile in profiles]
                    }
        return HttpResponse(simplejson.dumps(data))
    return HttpResponseRedirect(reverse('consulting_index'))

@login_required()
@only_doctor_administrative
def select_doctor(request, id_patient):
    patient_user = get_object_or_404(User, pk=int(id_patient))
    if request.method == 'POST':
        form = DoctorSelectionForm(request.POST)

        if form.is_valid():
            profile = patient_user.get_profile()
            check_transfer(request, id_patient, True)
            profile.doctor = User.objects.get(pk=int(form.cleaned_data['doctor']))
            profile.save()
            if request.is_ajax():
                return HttpResponse('OK');
            return HttpResponseRedirect(reverse('cal.scheduler',
                args=[int(id_patient)]))
        elif request.is_ajax():
            return Http404
    else:
        form = DoctorSelectionForm()

    return render_to_response('cal/app/select_doctor.html', {'form': form,
        'patient_user': patient_user},
        context_instance=RequestContext(request))

@login_required()
@only_doctor_administrative
def check_transfer(request, id_patient, doit=False):
    if request.method == 'POST':
        id_doctor = request.POST.get('doctor',None)
    else:
        return Http404
    transferable, moves = True, 0
    patient_user = get_object_or_404(User, pk=int(id_patient))
    doctor = get_object_or_404(User, pk=int(id_doctor))
    next_apps = Appointment.objects.filter(patient=patient_user,
                            date__gt=date.today(), status__in=[settings.CONFIRMED, settings.RESERVED]).order_by(
                            'date')
    for app in next_apps:
        available, free_intervals = Appointment.objects.availability(
                doctor, app.date, app)
        transferable = available
        if not available and free_intervals:
            for i in free_intervals:
                if i['duration'] >= app.duration:
                    moves += 1
                    transferable = True
                    if doit:
                        app.start_time = i['start_time']
                        app.end_time = add_minutes(i['start_time'], app.duration)
                    break
        if doit:
            if transferable:
                app.doctor = doctor
                #app.description = "%s %s"%(app.app_type.description, app.description)
                #app.app_type = None
            else:
                app.status = settings.CANCELED_BY_DOCTOR
            app.save()
    data = {'ok': transferable,
            'moves': moves}
    if doit:
        return 1
    else:
        return HttpResponse(simplejson.dumps(data))

@login_required
@only_doctor_administrative
@paginate(template_name='cal/payment/list_ajax.html',
    list_name='events', objects_per_page=settings.OBJECTS_PER_PAGE*2)
def get_payment_list(request, query_filter=None):
    apps = Appointment.objects.all().order_by('-date')
    if query_filter:
        apps = apps.filter(query_filter)
    if request.user.get_profile().is_doctor():
        apps = apps.filter(doctor=request.user)

    queries_without_page = request.GET.copy()
    if queries_without_page.has_key('page'):
        del queries_without_page['page']

    template_data = dict(user=request.user,
                        events=apps,
                        queries=queries_without_page,
                        context_instance=RequestContext(request))
    return template_data

@login_required
@only_doctor_administrative
def payment_list(request):
    form = PaymentFiltersForm()
    if request.method == "GET":
        form = PaymentFiltersForm(request.GET, user=request.user)
        query_filter = Q()
        exclude_filter = Q()
        for k, v in request.GET.items():
            if not v:
                continue
            if k.startswith('app_date'):
                day, month, year  = v.split('/')
                if k.endswith('0'):
                    query_filter = query_filter & Q(date__gte=date(int(year),
                                                                int(month),
                                                                int(day)))
                else:
                    query_filter = query_filter & Q(date__lte=date(int(year),
                                                                int(month),
                                                                int(day)))
            elif k.startswith('payment_date'):
                day, month, year  = v.split('/')
                if k.endswith('0'):
                    query_filter = query_filter \
                            & Q(payment_appointment__date__gte=date(int(year),
                                                                int(month),
                                                                int(day)))
                else:
                    query_filter = query_filter \
                            & Q(payment_appointment__date__lte=date(int(year),
                                                                int(month),
                                                                int(day)))
            elif k.startswith('value'):
                if k.endswith('0'):
                    query_filter = query_filter \
                            & Q(payment_appointment__value__gte=Decimal(v))
                else:
                    query_filter = query_filter \
                            & Q(payment_appointment__value__lte=Decimal(v))
            elif k.startswith('discount'):
                if k.endswith('0'):
                    query_filter = query_filter \
                            & Q(payment_appointment__discount__gte=int(v))
                else:
                    query_filter = query_filter \
                            & Q(payment_appointment__discount__lte=int(v))
            elif k.startswith('method'):
                query_filter = query_filter \
                    & Q(payment_appointment__method__in=request.GET.getlist(k))
            elif k.startswith('patient'):
                query_filter = query_filter \
                    & Q(patient__id__in=request.GET.getlist(k))
            elif k.startswith('doctor'):
                query_filter = query_filter \
                    & Q(doctor__id__in=request.GET.getlist(k))
            elif k.startswith('status'):
                subquery = Q()
                for op in request.GET.getlist(k):
                    if int(op)==0:
                        subquery = subquery \
                        | Q(payment_appointment__method__gte=0)
                    elif int(op)==1:
                        subquery = subquery \
                            | (Q(status=settings.CONFIRMED) \
                            & Q(date__gte=date.today()))
                    elif int(op)==2:
                        subquery = subquery \
                                    | Q(status=settings.CONFIRMED) \
                                    & Q(appointment_conclusions__id__gt=0) \
                                    & Q(payment_appointment__isnull=True)
                    elif int(op)==3:
                        subquery = subquery \
                                    | Q(status=settings.RESERVED) \
                                    & Q(date__gte=date.today())
                    elif int(op)==4:
                        subquery = subquery \
                                    | Q(status=settings.CANCELED_BY_DOCTOR) \
                                    | Q(status=settings.CANCELED_BY_PATIENT)
                    elif int(op)==5:
                        subquery = subquery \
                                    | Q(status=settings.RESERVED) \
                                    & Q(date__lt=date.today())
                    elif int(op)==6:
                        subquery = subquery \
                                    | Q(status=settings.CONFIRMED) \
                                    & Q(appointment_conclusions__isnull=True) \
                                    & Q(appointment_tasks__isnull=True) \
                                    & Q(date__lt=date.today())
                query_filter = query_filter & subquery
        if request.is_ajax():
            return get_payment_list(request, query_filter)

    return render_to_response('cal/payment/list.html', {'form': form},
        context_instance=RequestContext(request))

@login_required
@only_doctor_administrative
def payment_edit(request, id_appointment):
    app = get_object_or_404(Appointment, pk=int(id_appointment))
    payment = None
    try:
        payment = Payment.objects.get(appointment=app)
        form = PaymentForm(instance=payment)
    except:
        form = PaymentForm()
    if request.method == 'POST':
        form = PaymentForm(request.POST)
        if payment:
            form = PaymentForm(request.POST, instance=payment)
        if form.is_valid():
            payment = form.save(commit=False)
            payment.created_by = request.user
            payment.appointment = app
            payment.save()
            return HttpResponseRedirect(reverse('cal.list_payment'))

    return render_to_response('cal/payment/edit.html', {'form': form,
        'app': app},
        context_instance=RequestContext(request))


import os
import sys

def reduce_seqs(first,second,idx):
    """
    TA T --> error
    TA A --> TA
    T T --> TT
    A TT --> ATT
    AA * --> AA
    """
    if not first:
        return second
    if len(first) == 1:
        return first + second
    if second == "*":
        return first
    if (len(first) > (idx + 1 )):
        assert (first[idx:] == second[idx:len(first)-1])
    return first[:idx+1] + second[len(first)- idx:]
    # return first[:idx] + second[:len(first)-1]

def fix_lines(lines, samples):

    if len(lines) == 1:
        return lines[0]
    final_ref = ""

    sample_gts1 = {s: "" for s in samples}
    sample_gts2 = {s: "" for s in samples}
    for idx_line, l in enumerate(lines):
        vec = l.split()
        ref = vec[3]
        # pos = int(vec[1])
        alts = {i: x for i, x in enumerate(vec[4].split(","))}

        gt_options = {k + 1: v for k, v in alts.items()}
        gt_options[0] = ref

        final_ref=reduce_seqs(final_ref,ref,idx_line)
        # ref = "".join([ref_tmp[i] for i in range(pos - i, pos)]) + ref

        format_f = vec[8]
        for idx, sample in enumerate(samples):
            gt_index = [i for i, x in enumerate(format_f.split(":")) if x == "GT"][0]
            gt = vec[9 + idx].split(":")[gt_index].replace("|","/")
            gt1,gt2 = gt.split("/")
            gt1,gt2 = int(gt1),int(gt2)
            sample_gts1[sample] = reduce_seqs(sample_gts1[sample],gt_options[gt1],idx_line)
            sample_gts2[sample] = reduce_seqs(sample_gts2[sample],gt_options[gt2],idx_line)
    alts = list(set(list(sample_gts1.values()) + list(sample_gts2.values())) - set([final_ref]) )
    ref_and_alts = [final_ref] + alts
    gts = []
    for sample in samples:
        alt1 = sample_gts1[sample]
        alt2 = sample_gts2[sample]
        alt = str(ref_and_alts.index(alt1)) + "/" + str(ref_and_alts.index(alt2))
        gts.append(alt)

    new_lines = lines[0].split("\t")
    new_lines[3] = final_ref
    new_lines[4] = ",".join(alts)

    for idx,s in enumerate(samples):
        new_lines[9 + idx] = gts[idx] + ":" + ":".join(new_lines[9 + idx].split(":")[1:])

    return "\t".join(new_lines)

if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(description='fix vcf errors')
    parser.add_argument('vcf_in')
    parser.add_argument('-v', '--verbose', action='store_true')
    parser.add_argument('-o', '--output',default=None)

    args = parser.parse_args()

    if args.verbose:
        os.environ["verbose"] = "y"
    if args.output:
        hw = open(args.output,"w")
    else:
        hw = sys.stdout

    try:
        if args.vcf_in != "-":
            h = open(args.vcf_in)
        else:
            h = sys.stdin
        prevlines = []
        prevpos = None
        for l in h:
            if l.startswith("#CHROM"):
                samples = l.split()[9:]
            if l.startswith("#"):
                hw.write(l)
            else:
                vec = l.split()
                pos = int(vec[1])
                if not prevlines:
                    prevlines.append(l)
                    prevpos = pos
                else:
                    if prevpos == (pos - 1):
                        prevlines.append(l)
                        prevpos = pos
                    else:
                        try:
                            fixed_lines = fix_lines(prevlines, samples)
                            hw.write(fixed_lines)
                        except:
                            for l in  prevlines:
                                hw.write(l)

                        prevlines = [l]
                        prevpos = pos
        hw.write(fix_lines(prevlines, samples))
    finally:
        if args.vcf_in != "-":
            h.close()
        hw.close()


# Напишите функцию, которая получает на вход директорию и рекурсивно обходит её и все вложенные директории. Результаты обхода сохраните в файлы json, csv и pickle.
# Для дочерних объектов указывайте родительскую директорию.
# Для каждого объекта укажите файл это или директория.
# Для файлов сохраните его размер в байтах, а для директорий размер файлов в ней с учётом всех вложенных файлов и директорий.

import csv
import json
import os
import pickle

def size(directory: str) -> float:
    size = 0
    if os.path.isfile(directory):
        size += os.path.getsize(directory)
    for i in os.walk(directory):
        for j in i[2]:
            size += os.path.getsize(str(f'{i[0]}\{j}'))
    return size

def information(directory):
    path = os.path.split(directory)
    if os.path.isdir(directory):
        type_ = 'директория'
    else:
        type_ = 'файл'
    dct = {'родительская директория': path[0], 'тип': type_, 'размер': size(directory)}
    return dct

def dir_walker_(directory, dct = None):
    if dct is None:
        dct = {}
    for item in os.listdir(directory):
        check_path = os.path.join(directory, item)
        dct[item] = {'информация': information(check_path)}
        if os.path.isdir(check_path):
            dir_walker_(check_path, dct[item])
    return dct

def dir_walker(directory: str, dct = None ) -> dict[str, dict[str]]:
    path = os.path.split(directory)
    if dct is None:
        dct = {directory: {'имя': path[1], 'родительская директория': path[0], 'тип': 'директория', 'размер': size(directory)}}
    for item in os.listdir(directory):
        check_path = os.path.join(directory, item)
        if os.path.isfile(check_path):
            dct[check_path] ={'имя': item, 'родительская директория': directory, 'тип': 'файл', 'размер': size(check_path)}
        elif os.path.isdir(check_path):
            dct[check_path] = {'имя': item, 'родительская директория': directory, 'тип': 'директория', 'размер': size(check_path)}
            dir_walker(check_path, dct)
    return dct

def jsn_writer(directory: str) -> None:
    with open('D:\GB\ДЗ\Погружение в Python\ДЗ8\\file.json', 'w', encoding='utf-8') as f:
        json.dump(dir_walker_(directory), f, ensure_ascii=False, indent=2)

def csv_writer(directory: str) -> None:
    dct = dir_walker(directory)
    all_data = []
    for _, j in dct.items():
        all_data.append(j)
    with open('D:\GB\ДЗ\Погружение в Python\ДЗ8\\file.csv', 'w', newline='', encoding='utf-8') as f:
        csv_write = csv.DictWriter(f, fieldnames=['имя', 'родительская директория', 'тип', 'размер'],dialect='excel-tab', quoting=csv.QUOTE_ALL)
        csv_write.writeheader()
        csv_write.writerows(all_data)

def pcl_writer(directory: str) -> None:
    dct = dir_walker(directory)
    with open('D:\GB\ДЗ\Погружение в Python\ДЗ8\\file.pickle', 'wb') as f:
        pickle.dump(dct, f)

if __name__ == '__main__':
    jsn_writer('D:\\GB\\ДЗ\\Погружение в Python')
    csv_writer('D:\\GB\\ДЗ\\Погружение в Python')
    pcl_writer('D:\\GB\\ДЗ\\Погружение в Python')


# coding:utf-8
import wx

class AutoSyncDialog(wx.Dialog):
    pass

class BatchTaskDialog(wx.Dialog):
    def __init__(self, parent, title, data):
        wx.Dialog.__init__(self, parent, title=title)
        self.parent = parent
        self._data = data
        self.do_layouts()
        self.do_binds()
        self.update()

    def do_layouts(self):
        self.lb = lb = wx.CheckListBox(self, -1, (80, 50), wx.DefaultSize, self._data)
        main_sizer = wx.BoxSizer(wx.VERTICAL)
        main_sizer.Add(lb, 7, wx.EXPAND)

        self.cb = cb = wx.CheckBox(self, -1, u'全选')
        main_sizer.Add(cb, 1, wx.EXPAND | wx.LEFT, 5)

        btn_sizer = wx.StdDialogButtonSizer()
        ok_btn = wx.Button(self, id=wx.ID_OK, label=u'确定')
        ok_btn.Enable(False)
        self.ok_btn = ok_btn
        cancel_btn = wx.Button(self, id=wx.ID_CANCEL, label=u'取消')
        btn_sizer.AddButton(ok_btn, )
        btn_sizer.AddButton(cancel_btn)
        btn_sizer.Realize()  # important!!

        main_sizer.AddSizer(btn_sizer, 2, wx.ALIGN_RIGHT)
        self.SetSizer(main_sizer)
        self.Fit()

    def do_binds(self):
        self.Bind(wx.EVT_CHECKBOX, self.OnToggleSelectAll, self.cb)
        self.Bind(wx.EVT_CHECKLISTBOX, self.OnToggleSelectLB, self.lb)

    def update(self):
        raw_title = self.GetTitle()
        frags = raw_title.split()
        suffix = '%d/%d' % self.count_items()
        if len(frags) == 1:
            frags.append(suffix)
        elif len(frags) == 2:
            frags[-1] = suffix
        new_title = ' '.join(frags)
        self.SetTitle(new_title)
    #     toggle`ok` button status
        self.ok_btn.Enable(len(self.get_checked_items()) > 0)

    def get_items_count(self):
        return len(self.lb.GetItems())

    def get_checked_items(self):
        _checked = []
        count = self.get_items_count()
        for i in range(count):
            if self.lb.IsChecked(i):
                _checked.append(i)
        return _checked

    def count_items(self):
        '''

        :return: (checked_items_count, all_items_count)
        '''
        return len(self.get_checked_items()), self.get_items_count()

    def OnToggleSelectAll(self, e):
        items_count = self.get_items_count()
        if e.IsChecked():
            for i in range(items_count):
                self.lb.Check(i)
        else:
            for i in range(items_count):
                self.lb.Check(i, check=False)
        self.update()

    def OnToggleSelectLB(self, event):
        index = event.GetSelection()
        if self.lb.IsChecked(index):
            self.lb.SetSelection(index)  # so that (un)checking also selects (moves the highlight)
        self.update()


import os
import sys
import subprocess
import unittest
import glob
import shutil
from typing import Optional, List, Dict
from pathlib import Path

# 3rd
from ROOT import TFile

# basf2
from basf2 import find_file
from b2test_utils import clean_working_directory, is_ci

def light_release() -> bool:
    """Returns true if we're in a light release"""
    try:
        # pylint: disable=import-outside-toplevel
        # pylint: disable=unused-import
        import generators  # noqa
    except ModuleNotFoundError:
        return True
    return False

def _touch_file_default(path: str):
    Path(path).touch()

def _touch_file_with_root(path: str) -> None:
    f = TFile(path, "NEW")
    f.Close()
    assert Path(path).is_file()

def _touch_file_with_subprocess(path: str) -> None:
    subprocess.run(["touch", path]).check_returncode()

def _touch_file_with_subprocess_and_root(path: str) -> None:
    filename = Path(path).name
    working_dir = Path(path).parent
    cmd = ["root", "-x", "-l", "-q", "-e", f"TFile f(\"{filename}\", \"NEW\"); if (not f.IsOpen()) gSystem->Exit(1);"]
    subprocess.run(cmd, cwd=working_dir).check_returncode()

def _touch_file_test(method, path: str, **kwargs):
    try:
        method(path, **kwargs)
    except Exception as e:
        print(f"{method.__name__}: Tried to touch file with, but failed: {e}")
    else:
        print(f"{method.__name__}: Successfully touched file")
        Path(path).unlink()

def _permission_report(folder: str) -> None:
    """Quick helper function to show permissions of folder and a selection
    of files in it
    """
    folder = Path(folder)
    print("-" * 80)
    print(f"Permissions of {folder}: {folder.stat()}")
    content = list(folder.iterdir())
    if content:
        print(
            f"Permission of one of its contents. {content[0]}: "
            f"{content[0].stat()}"
        )
    test_file = folder / "Bd2JpsiKS.root"
    methods = [
        _touch_file_default,
        _touch_file_with_root,
        _touch_file_with_subprocess,
        _touch_file_with_subprocess_and_root
    ]
    for method in methods:
        _touch_file_test(method, str(test_file))
    print("-" * 80)

class SteeringFileTest(unittest.TestCase):
    """Test steering files"""

    def _test_examples_dir(
        self,
        path_to_glob: str,
        broken: Optional[List[str]] = None,
        additional_arguments: Optional[List[str]] = None,
        expensive_tests: Optional[List[str]] = None,
        skip_in_light: Optional[List[str]] = None,
        skip: Optional[List[str]] = None,
        n_events: Optional[Dict[str, int]] = None,
    ):
        """
        Internal function to test a directory full of example scripts with an
        optional list of broken scripts to be skipped.

        Parameters:
            path_to_glob (str): the path to a directory to search for python
                scripts (must end in .py)
            broken (list(str)): (optional) names of scripts that are known to
                be broken and can be skipped
            additional_arguments (list(str)): (optional) additional arguments
                for basf2 to be passed when testing the scripts
            expensive_tests (list(str)): (optional) names of scripts that take
                longer and should e.g. not run on bamboo
            skip_in_light (list(str)): (optional) names of scripts that have to
                be excluded in light builds
            skip (list(str)): (optional) names of scripts to always skip
            n_events (dict(str, int)): mapping of name of script to number of
                required events for it to run (`-n` argument). If a filename
                isn't listed, we assume 1
        """
        if additional_arguments is None:
            additional_arguments = []
        if broken is None:
            broken = []
        if expensive_tests is None:
            expensive_tests = []
        if skip_in_light is None:
            skip_in_light = []
        if skip is None:
            skip = []
        if n_events is None:
            n_events = {}
        # we have to copy all the steering files (plus other stuffs, like decfiles) we want to test
        # into a new directory and then cd it as working directory when subprocess.run is executed,
        # otherwise the test will fail horribly if find_file is called by one of the tested steerings.
        original_dir = find_file(path_to_glob)
        print(f"Our user id: {os.getuid()}")
        _permission_report(original_dir)
        working_dir = find_file(shutil.copytree(original_dir, "working_dir"))
        _permission_report(working_dir)
        # Add write permissions for user to this directory
        os.chmod(working_dir, 0o744)
        _permission_report(working_dir)
        all_egs = sorted(glob.glob(working_dir + "/*.py"))
        for eg in all_egs:
            filename = os.path.basename(eg)
            if filename in broken:
                continue
            if is_ci() and filename in expensive_tests:
                continue
            if light_release() and filename in skip_in_light:
                continue
            if filename in skip:
                continue
            with self.subTest(msg=filename):
                # pylint: disable=subprocess-run-check
                result = subprocess.run(
                    [
                        "basf2",
                        "-n",
                        str(n_events.get(filename, 1)),
                        eg,
                        *additional_arguments,
                    ],
                    stdout=subprocess.PIPE,
                    stderr=subprocess.STDOUT,
                    cwd=working_dir,
                )
                if result.returncode != 0:
                    # failure running example so let's print the output
                    # on stderr so it's not split from output of unittest
                    # done like this since we don't want to decode/encode utf8
                    sys.stdout.buffer.write(result.stdout)
                self.assertEqual(result.returncode, 0)

    # fixme: This should be made to run on buildbot, i.e. by adding the/some
    #   files to the examples/validation directory
    @unittest.skipIf(
        not os.path.exists(
            find_file(
                "starterkit/2021/1111540100_eph3_BGx0_1.root",
                "examples",
                silent=True,
            )
        ),
        "Test data files not found.",
    )
    def test_lessons_1_to_5(self):
        """Test lesson on basf2 basics."""
        self._test_examples_dir(
            path_to_glob="online_book/basf2/steering_files",
            additional_arguments=["1"],
            expensive_tests=["065_generate_mc.py", "067_generate_mc.py"],
            skip_in_light=[
                "065_generate_mc.py",
                "067_generate_mc.py",
                "085_module.py",
                "087_module.py",
            ],
            n_events={
                # See https://questions.belle2.org/question/11344/
                "091_cs.py": 3000,
            },
        )

if __name__ == "__main__":
    with clean_working_directory():
        unittest.main()


"""empty message

Revision ID: b61d4a1d56a7
Revises:
Create Date: 2022-02-13 19:21:42.196543

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = 'b61d4a1d56a7'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('member',
    sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
    sa.Column('username', sa.String(), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_table('sheet',
    sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
    sa.Column('sheet_name', sa.String(), nullable=True),
    sa.Column('member_id', sa.Integer(), nullable=True),
    sa.ForeignKeyConstraint(['member_id'], ['member.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_table('item',
    sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
    sa.Column('item_name', sa.String(), nullable=True),
    sa.Column('sheet_id', sa.Integer(), nullable=True),
    sa.ForeignKeyConstraint(['sheet_id'], ['sheet.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('item')
    op.drop_table('sheet')
    op.drop_table('member')
    # ### end Alembic commands ###


# By @kirito6969 for PepeBot
# Don't edit credits Madafaka
"""
This module can search images in danbooru and send in to the chat!
──「 **Danbooru Search** 」──
"""

import os
import urllib

import requests

from userbot import catub

from ..helpers.functions import age_verification
from . import edit_delete, edit_or_reply, reply_id, useless

plugin_category = "useless"

@catub.cat_cmd(
    pattern="ani(mu|nsfw) ?([\s\S]*)",
    command=("ani", plugin_category),
    info={
        "header": "Contains NSFW 🔞.\nTo search images in danbooru!",
        "usage": [
            "{tr}animu <query>",
            "{tr}aninsfw <nsfw query>",
        ],
        "examples": [
            "{tr}animu naruto",
            "{tr}aninsfw naruto",
        ],
    },
)
async def danbooru(event):
    "Get anime charecter pic or nsfw"
    reply_to = await reply_id(event)
    if await age_verification(event, reply_to):
        return
    await edit_or_reply(event, "`Processing…`")
    flag = await useless.importent(event)
    if flag:
        return
    rating = "Explicit" if "nsfw" in event.pattern_match.group(1) else "Safe"
    search_query = event.pattern_match.group(2)
    params = {
        "limit": 1,
        "random": "true",
        "tags": f"Rating:{rating} {search_query}".strip(),
    }
    with requests.get(
        "http://danbooru.donmai.us/posts.json", params=params
    ) as response:
        if response.status_code == 200:
            response = response.json()
        else:
            return await edit_delete(
                event, f"**An error occurred, response code: **`{response.status_code}`"
            )

    if not response:
        return await edit_delete(event, f"**No results for query:** __{search_query}__")
    valid_urls = [
        response[0][url]
        for url in ["file_url", "large_file_url", "source"]
        if url in response[0].keys()
    ]
    if not valid_urls:
        return await edit_delete(
            event, f"**Failed to find URLs for query:** __{search_query}__"
        )
    for image_url in valid_urls:
        try:
            await event.client.send_file(event.chat_id, image_url, reply_to=reply_to)
            await event.delete()
            return
        except Exception as e:
            await edit_or_reply(event, f"{e}")
    await edit_delete(event, f"**Failed to fetch media for query:** __{search_query}__")

@catub.cat_cmd(
    pattern="boobs(?:\s|$)([\s\S]*)",
    command=("boobs", plugin_category),
    info={
        "header": "NSFW 🔞\nYou know what it is, so do I !",
        "usage": "{tr}boobs",
        "examples": "{tr}boobs",
    },
)
async def boobs(e):
    "Search boobs"
    reply_to = await reply_id(e)
    if await age_verification(e, reply_to):
        return
    a = await edit_or_reply(e, "`Sending boobs...`")
    flag = await useless.importent(e)
    if flag:
        return
    nsfw = requests.get("http://api.oboobs.ru/noise/1").json()[0]["preview"]
    urllib.request.urlretrieve(f"http://media.oboobs.ru/{nsfw}", "boobs.jpg")
    await e.client.send_file(e.chat_id, "boobs.jpg", reply_to=reply_to)
    os.remove("boobs.jpg")
    await a.delete()

@catub.cat_cmd(
    pattern="butts(?:\s|$)([\s\S]*)",
    command=("butts", plugin_category),
    info={
        "header": "NSFW 🔞\nBoys and some girls likes to Spank this 🍑",
        "usage": "{tr}butts",
        "examples": "{tr}butts",
    },
)
async def butts(e):
    "Search beautiful butts"
    reply_to = await reply_id(e)
    if await age_verification(e, reply_to):
        return
    a = await edit_or_reply(e, "`Sending beautiful butts...`")
    flag = await useless.importent(e)
    if flag:
        return
    nsfw = requests.get("http://api.obutts.ru/butts/10/1/random").json()[0]["preview"]
    urllib.request.urlretrieve(f"http://media.obutts.ru/{nsfw}", "butts.jpg")
    await e.client.send_file(e.chat_id, "butts.jpg", reply_to=reply_to)
    os.remove("butts.jpg")
    await a.delete()


"""External task that waits for SIP validation in DPS."""
import os
from datetime import datetime, timedelta, timezone

import dateutil.parser
from siptools_research.config import Configuration
from siptools_research.remoteanytarget import RemoteAnyTarget
from siptools_research.utils.database import Database
from siptools_research.workflow.send_sip import SendSIPToDP
from siptools_research.workflowtask import WorkflowExternalTask

class ValidateSIP(WorkflowExternalTask):
    """External task that completes when SIP has been validated.

    The SIP is validated when ingest report is available in ~/rejected/
    or ~/accepted/ directories in digital preservation system.

    Task requires that SIP is sent to digital preservation service.
    """

    def requires(self):
        """List the Tasks that this Task depends on.

        :returns: SendSIPToDP task
        """
        return SendSIPToDP(workspace=self.workspace,
                           dataset_id=self.dataset_id,
                           config=self.config)

    def output(self):
        """Return the output target of this Task.

        :returns: remote target that may exist on digital preservation
                  server in any path formatted::

                      ~/accepted/<datepath>/<document_id>.tar/
                      ~/rejected/<datepath>/<document_id>.tar/

                  where datepath is any date between the date the SIP
                  was sent to the server and the current date.

        :rtype: RemoteAnyTarget
        """
        conf = Configuration(self.config)
        database = Database(self.config)

        # Get SendSIPToDP completion datetime or use the current UTC
        # time. This is necessary since ValidateSip output is checked
        # first time before any of the dependencies are ran.
        # Dependencies are ran only if ValidateSip task is not
        # completed.
        try:
            send_timestamp = database.get_task_timestamp(
                self.document_id, "SendSIPToDP"
            )
            sip_to_dp_date = dateutil.parser.parse(send_timestamp).date()
        except (ValueError, KeyError):
            sip_to_dp_date = datetime.now(timezone.utc).date()

        lim_date = datetime.today().date()

        paths = []
        while sip_to_dp_date <= lim_date:
            paths.append(
                os.path.join(
                    f'accepted/{sip_to_dp_date}/{self.document_id}.tar'
                )
            )
            paths.append(
                os.path.join(
                    f'rejected/{sip_to_dp_date}/{self.document_id}.tar'
                )
            )
            sip_to_dp_date += timedelta(days=1)

        return RemoteAnyTarget(
            paths,
            host=conf.get('dp_host'),
            port=int(conf.get('dp_port')),
            username=conf.get('dp_user'),
            keyfile=conf.get('dp_ssh_key')
        )


import numpy as np
import cv2
import keras
from models.psenet import psenet
from tool.utils import ufunc_4 , scale_expand_kernels ,fit_minarearectange,fit_boundingRect_2,text_porposcal

inputs = keras.layers.Input(shape = (None,None,3))
outputs = psenet(inputs)
model = keras.models.Model(inputs,outputs)
model.load_weights('resent50-190219_BLINEAR-iou8604.hdf5')

MIN_LEN = 640
MAX_LEN = 1240

def predict(images):
    h,w = images.shape[0:2]
    if(w<h):
        if(h<MIN_LEN):
            scale = 1.0 * MIN_LEN / h
            w = w * scale
            h = MIN_LEN
        elif(h>MAX_LEN):
            scale = 1.0 * MAX_LEN / h
            w = w * scale
            h = MAX_LEN
    elif(h<=w ):
        if(w<MIN_LEN):
            scale = 1.0 * MIN_LEN /w
            h = scale * h
            w = MIN_LEN
        elif(w>MAX_LEN):
            scale = 1.0 * MAX_LEN /w
            h = scale * w
            h = MAX_LEN

    w = int(w //32 * 32)
    h = int(h//32 * 32)

    scalex = images.shape[1] / w
    scaley = images.shape[0] / h

    images = cv2.resize(images,(w,h),cv2.INTER_AREA)
    images = np.reshape(images,(1,h,w,3))

    res = model.predict(images[0:1,:,:,:])

    res1 = res[0]
    res1[res1>0.9]= 1
    res1[res1<=0.9]= 0
    newres1 = []
    for i in [2,4]:
        n = np.logical_and(res1[:,:,5],res1[:,:,i]) * 255
        newres1.append(n)
    newres1.append(res1[:,:,5]*255)

    num_label,labelimage = scale_expand_kernels(newres1,filter=False)
    rects = fit_boundingRect_2(num_label,labelimage)

    im = np.copy(images[0])
    for rt in rects:
        cv2.rectangle(im,(rt[0]*2,rt[1]*2),(rt[2]*2,rt[3]*2),(0,255,0),2)

    g = text_porposcal(rects,res1.shape[1],max_dist=8,threshold_overlap_v=0.3)
    rects = g.get_text_line()

    for rt in rects:
        cv2.rectangle(im,(rt[0]*2,rt[1]*2-2),(rt[2]*2,rt[3]*2),(0,0,255),2)
    cv2.imwrite('test.png',im)

    return rects


from flask import Flask, render_template, session, flash, request
from principal import *
import formulariosProveedor

@app.route('/addClienteEmp', methods=['GET', 'POST'])
def addClienteEmp():
    if session['privilegios'] != 'ADMINISTRADOR':
        return render_template('login.html')

    form_empresa = formulariosProveedor.formProveedor(request.form)

    if request.method == 'POST' and form_empresa.validate():
        CLIENTEEMP.insert({
            'rut': form_empresa.rut.data,
            'nombre': form_empresa.nombre.data,
            'ciudad': form_empresa.ciudad.data,
            'comuna': form_empresa.comuna.data,
            'correo':form_empresa.correo.data,
            'nombreContacto': form_empresa.nombreContacto.data,
            'celularContacto': form_empresa.celularContacto.data
        })
        flash('Empresa cliente ingresada correctamente')
        return render_template('index.html')

    return render_template('registrarClienteEmp.html', form=form_empresa, accion='Registrar')

@app.route('/editClienteEmp/<rutModificar>', methods=['GET', 'POST'])
def editClienteEmp(rutModificar):
    if session['privilegios'] != 'ADMINISTRADOR':
        return render_template('login.html')

    form_empresa = formulariosProveedor.formProveedor(request.form)
    ponerDatosOriginales = True

    if request.method == 'POST':

        form_empresa.rut.data = rutModificar
        form_empresa.nombre.data = request.form['nombre']
        form_empresa.ciudad.data = request.form['ciudad']
        form_empresa.comuna.data = request.form['comuna']
        form_empresa.correo.data = request.form['correo']
        form_empresa.nombreContacto.data = request.form['nombreContacto']
        form_empresa.celularContacto.data = request.form['celularContacto']
        ponerDatosOriginales = False

        if form_empresa.validate():
            PROVEEDORES.update_one({"rut": rutModificar}, {"$set": {
                'nombre': request.form['nombre'],
                'ciudad': request.form['ciudad'],
                'comuna': request.form['comuna'],
                'correo': request.form['correo'],
                'nombreContacto': request.form['nombreContacto'],
                'celularContacto': request.form['celularContacto']
            }})
            flash('Los datos de la Empresa se actualizaron correctamente.')
            return render_template('index.html')

    if ponerDatosOriginales:
        output = CLIENTEEMP.find_one({"rut": rutModificar})

        form_empresa.rut.data = rutModificar
        form_empresa.nombre.data = output['nombre']
        form_empresa.ciudad.data = output['ciudad']
        form_empresa.comuna.data = output['comuna']
        form_empresa.correo.data = output['correo']
        form_empresa.nombreContacto.data = output['nombreContacto']
        form_empresa.celularContacto.data = output['celularContacto']

    return render_template('registrarProveedor.html', form=form_empresa, accion='Modificar')

@app.route('/deleteClienteEmp/<rutEliminar>')
def deleteClienteEmp(rutEliminar):
    if session['privilegios'] != 'ADMINISTRADOR':
        return render_template('login.html')

    CLIENTEEMP.delete_one({ 'rut': rutEliminar })
    flash('Empresa Cliente eliminada Correctamente')
    return render_template('index.html')

@app.route('/listClienteEmp', methods=['GET', 'POST'])
def listClienteEmp():

    output = CLIENTEEMP.find()
    return render_template('listarClienteEmp.html', empresas=output)


import os
import subprocess
from tkinter import *
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from reportlab.lib import colors
from reportlab.graphics.shapes import (Drawing, Rect, String, Line, Group)
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

root = Tk()
root.title("Doctor's Card")
root.geometry("600x500+300+100")

pdfmetrics.registerFont(TTFont('Trebuchet MS', '..\\fonts\\trebuc.ttf'))
pdfmetrics.registerFont(TTFont('Caladea', '..\\fonts\\Caladea-Bold.ttf'))
pdfmetrics.registerFont(TTFont('ErasMediumITC', '..\\fonts\\ErasMediumITC.ttf'))
pdfmetrics.registerFont(TTFont('FRADM', '..\\fonts\\FRADM.ttf'))

directory_name = r"Silent_Garden_Detalis\Doctor Card"
home_directory = os.path.expanduser("~")
directory_path = os.path.join(home_directory, directory_name)

if not os.path.exists(directory_path):
    os.makedirs(directory_path)

selection_path = os.path.join(directory_path, "card.png")

def main():
    label_main = ttk.Label(root, text="Doctor's Card", bootstyle=SUCCESS, font="Helvetica 20 bold").grid(row=0, column=0, sticky=W, padx=10)
    label1 = ttk.Label(root, text="Name", font="Helvetica 15", bootstyle=DARK).grid(row=1, column=0, sticky=W, pady=10, padx=10)
    label2 = ttk.Label(root, text="Age", font="Helvetica 15", bootstyle=DARK).grid(row=2, column=0, sticky=W, pady=10, padx=10)
    label3 = ttk.Label(root, text="Birthday", font="Helvetica 15", bootstyle=DARK).grid(row=3, column=0, sticky=W, pady=10, padx=10)
    label4 = ttk.Label(root, text="Package", font="Helvetica 15", bootstyle=DARK).grid(row=4, column=0, sticky=W, pady=10, padx=10)
    label5 = ttk.Label(root, text="Arrival", font="Helvetica 15", bootstyle=DARK).grid(row=5, column=0, sticky=W, pady=10, padx=10)
    label6 = ttk.Label(root, text="Departure", font="Helvetica 15", bootstyle=DARK).grid(row=7, column=0, sticky=W, pady=10, padx=10)

    label20 = ttk.Label(root, text=":", font="Helvetica 15", bootstyle=DARK).grid(row=1, column=1, sticky=W, pady=10, padx=10)
    label21 = ttk.Label(root, text=":", font="Helvetica 15", bootstyle=DARK).grid(row=2, column=1, sticky=W, pady=10, padx=10)
    label22 = ttk.Label(root, text=":", font="Helvetica 15", bootstyle=DARK).grid(row=3, column=1, sticky=W, pady=10, padx=10)
    label23 = ttk.Label(root, text=":", font="Helvetica 15", bootstyle=DARK).grid(row=4, column=1, sticky=W, pady=10, padx=10)
    label24 = ttk.Label(root, text=":", font="Helvetica 15", bootstyle=DARK).grid(row=5, column=1, sticky=W, pady=10, padx=10)
    label25 = ttk.Label(root, text=":", font="Helvetica 15", bootstyle=DARK).grid(row=7, column=1, sticky=W, pady=10, padx=10)

    global input_name
    input_name = ttk.Entry(root, font="Arial 12", bootstyle=DARK, width=30)
    input_name.grid(row=1, column=2, columnspan=3, sticky=W, pady=10, padx=10)
    global input_age
    input_age = ttk.Entry(root, font="Arial 12", bootstyle=DARK, width=6)
    input_age.grid(row=2, column=2, sticky=W, pady=10, padx=10)
    label_age = ttk.Label(root, text="years", font="Arial 12", bootstyle=DARK).grid(row=2, column=3, sticky=W, pady=10, padx=10)
    global input_birthday
    input_birthday = ttk.Entry(root, font="Arial 12", bootstyle=DARK, width=11)
    input_birthday.grid(row=3, column=2, columnspan=3, sticky=W, padx=10, pady=10)

    package_values = ["Ayurveda Regeneration Package", "Ayurveda Panchakarma Package", "Ayurveda Slimming Package"]
    global input_package
    input_package = ttk.Combobox(root, values=package_values, width=28, state='readonly', font='Arial 12')
    input_package.grid(row=4, column=2, columnspan=3, sticky=W, pady=8, padx=8)
    input_package.current(0)

    global input_arrival
    input_arrival = ttk.Entry(root, font="Arial 12", bootstyle=DARK, width=11)
    input_arrival.grid(row=5, column=2, columnspan=3, sticky=W, padx=10, pady=10)
    input_arrival.insert(END, "YYYY-MM-DD")

    global input_Departure
    input_Departure = ttk.Entry(root, font="Arial 12", bootstyle=DARK, width=11)
    input_Departure.grid(row=7, column=2, columnspan=3, sticky=W, padx=10, pady=10)
    input_Departure.insert(END, "YYYY-MM-DD")

    def first_checkbutton_checked():
        global first_checkbutton_checked_now
        first_checkbutton_checked_now = var1.get()
        if first_checkbutton_checked_now:
            input_time1.config(state="normal", bootstyle=DARK)
        else:
            input_time1.config(state="disabled", bootstyle=LIGHT)

    global var1
    var1 = IntVar()
    checkbox_notimespecified1 = ttk.Checkbutton(root, text="Time Not Specified", variable=var1, onvalue=0, offvalue=1, command=first_checkbutton_checked)
    checkbox_notimespecified1.grid(row=6, column=2, columnspan=3, sticky=W, padx=10, pady=10)

    global input_time1
    input_time1 = ttk.Entry(root, font="Arial 12", bootstyle=LIGHT, width=7, state="disabled")
    input_time1.grid(row=6, column=4, sticky=W, padx=10, pady=10)

    def second_checkbutton_checked():
        global second_checkbutton_checked_now
        second_checkbutton_checked_now = var2.get()
        if second_checkbutton_checked_now:
            input_time2.config(state="normal", bootstyle=DARK)
        else:
            input_time2.config(state="disabled", bootstyle=LIGHT)

    global var2
    var2 = IntVar()
    checkbox_notimespecified2 = ttk.Checkbutton(root, text="Time Not Specified", variable=var2, onvalue=0, offvalue=1, command=second_checkbutton_checked)
    checkbox_notimespecified2.grid(row=8, column=2, columnspan=3, sticky=W, padx=10, pady=10)

    global input_time2
    input_time2 = ttk.Entry(root, font="Arial 12", bootstyle=LIGHT, width=7, state="disabled")
    input_time2.grid(row=8, column=4, sticky=W, padx=10, pady=10)

    button_quit = ttk.Button(root, text='Quit', style='info.outline.TButton', command=quit_command)
    button_quit.grid(row=9, column=3, sticky=W, padx=10, pady=10)

    button_create = ttk.Button(root, text='Create', style='success.TButton', command=creating_card)
    button_create.grid(row=9, column=4, sticky=W, padx=10, pady=10)

    root.mainloop()

def quit_command():
    root.quit()

def creating_card():
    drawing = Drawing(500, 300)

    font_trebuchet = 'Trebuchet MS'
    font_caladea = 'Caladea'
    font_eras = 'ErasMediumITC'
    font_fradm = 'FRADM'

    font_size_for_name = 45
    font_size_for_4 = 20
    font_size_for_package = 30

    name_String = input_name.get()
    age_String = ""
    if input_age.get() == None or len(input_age.get().strip()) == 0 :
       age_String = ""
    else:
        age_String = f"Age : {input_age.get()} years"

    birthday_String = ""
    if input_birthday.get() == None or len(input_birthday.get().strip()) == 0 :
        birthday_String = ""
    else:
        birthday_String = f"Birthday : {input_birthday.get()}"

    package_String = input_package.get()

    arrival_time_string = ""
    if var1.get() == 0 :
        arrival_time_string = "Time Not Specified"
    else:
        arrival_time_string = input_time1.get()

    departure_time_string = ""
    if var2.get() == 0 :
        departure_time_string = "Time Not Specified"
    else:
        departure_time_string = input_time2.get()

    arrival_String = f"Arrival : {input_arrival.get()} [ {arrival_time_string} ]"
    departure_String = f"Departure : {input_Departure.get()} [ {departure_time_string} ]"

    name_Width = pdfmetrics.stringWidth(name_String, font_trebuchet, font_size_for_name)
    xcenter_name = (drawing.width / 2) - (name_Width / 2)

    position_age_birthday = drawing.width - 420

    package_Width = pdfmetrics.stringWidth(package_String, font_eras, font_size_for_package)
    xcenter_package = (drawing.width - package_Width) / 2

    position_arrival_departure = drawing.width - 475

    name = String(xcenter_name, 250, name_String, fontSize=font_size_for_name, fillColor=colors.black, fontName=font_trebuchet)
    age = String(position_age_birthday, 210, age_String, fontSize=font_size_for_4, fillColor=colors.black, fontName=font_caladea)
    birthday = String(position_age_birthday, 182, birthday_String, fontSize=font_size_for_4, fillColor=colors.black, fontName=font_caladea)
    package = String(xcenter_package, 135, package_String, fontSize=font_size_for_package, fillColor=colors.black, fontName=font_eras)
    arrival = String(position_arrival_departure, 75, arrival_String, fontSize=font_size_for_4, fillColor=colors.black, fontName=font_fradm)
    departure = String(position_arrival_departure, 40, departure_String, fontSize=font_size_for_4, fillColor=colors.black, fontName=font_fradm)

    drawing.add(name)
    drawing.add(age)
    drawing.add(birthday)
    drawing.add(package)
    drawing.add(arrival)
    drawing.add(departure)

    try:
        drawing.save(formats=['png'], outDir=directory_path, fnRoot="card")
        downloads_path = r'C:\Users\Admin\Downloads'
        subprocess.Popen(f'explorer /select, {selection_path}')
        root.quit()
    except Exception as e:
        print("Error:   ", str(e))

if __name__ == "__main__":
    main()