# Python imports
#import time
import json
#import datetime

# Django imports
from django.shortcuts import render_to_response, render, redirect
from django.http import HttpResponse

# LeakLess monitor imports
from Applications.Devices.Configuration.forms import ConfigurationControlForm
from Applications.Devices.models import *
from Applications.Users.views import *
from Applications.Measure.views import *
from LeakLessMonitor.base import *

def configuration_render(request):
    if request.user.is_authenticated():
        device_id           = request.GET.get('device_id')
        device_identifier   = request.GET.get('device_identifier')

        device_parameters=LldevicePdlagParameters.objects.filter(lldevicelist=device_id)

        if len(device_parameters)!=1:
            return HttpResponse("Parameters not fetched!")

        last_parameter_change= device_parameters[0].lastparameterchange

        parameter_info=LldevicePdlagParameterinfo.objects.filter(visible__gte=1)

        general_parameters  = configuration_return_parameter_data(device_parameters[0], parameter_info, "GENERAL")
        alarm_parameters    = configuration_return_parameter_data(device_parameters[0], parameter_info, "ALARM")
        measure_parameters  = configuration_return_parameter_data(device_parameters[0], parameter_info, "MEASURE")
        settings_parameters = configuration_return_parameter_data(device_parameters[0], parameter_info, "SETTINGS")

        group_array=[{'name_cro': "Generalno"   , 'name_eng': "General" , 'param_list': general_parameters},
                     {'name_cro': "Alarm"       , 'name_eng': "Alarm"   , 'param_list': alarm_parameters},
                     {'name_cro': "Mjerenje"    , 'name_eng': "Measure" , 'param_list': measure_parameters},
                     {'name_cro': "Postavke"    , 'name_eng': "Settings", 'param_list': settings_parameters}]


        user_action_list_html           = user_get_parameter_action_list(request)
        user_device_type                = user_get_device(request)
        unit_recalculation_window_html  = measure_get_unit_recalculation_window(request)


        return render_to_response('configuration.html',{'user_object'                       : request.user,
                                                        'user_device_type'                  : user_device_type,
                                                        'device_id'                         : device_id,
                                                        'device_identifier'                 : device_identifier,
                                                        'group_array'                       : group_array,
                                                        'lang'                              : user_get_language(request),
                                                        'last_parameter_change'             : last_parameter_change,
                                                        'user_action_list_html'             : user_action_list_html,
                                                        'unit_recalculation_window_html'    : unit_recalculation_window_html})
    else:
        return redirect(reverse('login_page'))


def configuration_control_form(request):
    user_language = user_get_language(request)

    if request.method == 'POST':
        # Ovdje je upis u bazu

        device_id = request.POST.get('device_id')
        device = devices_return_by_id(device_id)
        parameters = LldevicePdlagParameters.objects.get(lldevicelist=device)

        form = ConfigurationControlForm(user_language,request.POST)

        if form.is_valid():
            parameters.loc_cdo1 = int(form.cleaned_data['control_ch1_value_loc'])
            parameters.loc_cdo2 = int(form.cleaned_data['control_ch2_value_loc'])
            parameters.save()
            device.info_label1  = form.cleaned_data['control_ch1_label']
            device.info_label2  = form.cleaned_data['control_ch2_label']
            device.save()

            return HttpResponse('Ok')
        else:
            return HttpResponse('Error')

    else:
        # Ovdje je dohvat iz baze
        device_id = request.GET.get('device_id')
        device = devices_return_by_id(device_id)
        parameters = LldevicePdlagParameters.objects.get(lldevicelist=device)

        initial = {'control_ch1_label'      : device.info_label1,
                   'control_ch1_value_loc'  : parameters.get_loc_cdo1,
                   'control_ch1_value_rem'  : parameters.get_rem_cdo1,
                   'control_ch2_label'      : device.info_label2,
                   'control_ch2_value_loc'  : parameters.get_loc_cdo2,
                   'control_ch2_value_rem'  : parameters.get_rem_cdo2,}

        form = ConfigurationControlForm(initial=initial,lang=user_language)
        fields = list(form)

        field_group_ch1 = {
            'title'         : 'CH1',
            'class'         : 'panel-primary',
            'fields_dict'   :{
                'label'     : isolate_fields_by_name(fields, 'control_ch1_label'),
                'state_loc' : isolate_fields_by_name(fields, 'control_ch1_value_loc'),
                'state_rem' : isolate_fields_by_name(fields, 'control_ch1_value_rem'),
            }
        }

        if parameters.loc_cdo1 != parameters.rem_cdo1:
            field_group_ch1['class']='panel-warning'

        field_group_ch2 = {
            'title'         : 'CH2',
            'class'         : 'panel-primary',
            'fields_dict'   :{
                'label'     : isolate_fields_by_name(fields, 'control_ch2_label'),
                'state_loc' : isolate_fields_by_name(fields, 'control_ch2_value_loc'),
                'state_rem' : isolate_fields_by_name(fields, 'control_ch2_value_rem'),
            }
        }

        if parameters.loc_cdo2 != parameters.rem_cdo2:
            field_group_ch2['class']='panel-warning'

        return render_to_response(
            'configurationControlForm.html',{   'form_groups'       : [field_group_ch1,field_group_ch2],
                                                'device_id'         : device.id,
                                                'device_identifier' : device.rem_identifier,
                                                'device_type'       : device.loc_type,
                                                'lang'              : user_language},
            context_instance=RequestContext(request)
        )

def configuration_return_parameter_data(device_parameters,parameter_info, group_name):
    parameters = parameter_info.filter(group=group_name).order_by('idlldevice_pdlag_parameterinfo', 'subgroup')
    parameters_data = []
    for parameter_info in parameters:
        enum_list=[]

        value_loc = getattr(device_parameters, "loc_" + parameter_info.name.lower())
        value_rem = getattr(device_parameters, "rem_" + parameter_info.name.lower())
        value_loc_num = 0
        value_rem_num = 0
        if parameter_info.enumtext is not None:
            enum_list =parameter_info.enumtext.split(",")
            if value_loc is None:
                value_loc_num = 0
            else:
                value_loc_num = int(value_loc)

            if value_rem is None:
                value_rem_num = 0
            else:
                value_rem_num = int(value_rem)


        parameter_dict = {
            'info'              : parameter_info,
            'tmp_loc'           : str(value_loc),
            'tmp_rem'           : str(value_rem),
            'tmp_loc_num'       : value_loc_num,
            'tmp_rem_num'       : value_rem_num,
            'enum_list'         : enum_list
        }
        parameters_data.append(parameter_dict)
    return parameters_data


def configuration_write_parameter_changes_post(request):
    if request.user.is_authenticated():
        if request.is_ajax():
            if request.method == 'POST':
                return_data = json.loads(request.body)
                parameter_info_list     = LldevicePdlagParameterinfo.objects.all()
                device_id = return_data['device_id']
                parameter_list = return_data['parameter_list']
                fail_counter = 0
                success_counter = 0
                response_text =''
                error_parameter_list    = []
                success_parameter_list  = []
                parameter_dictionary    = {}

                if device_id is None:
                    data_response = {'ok': False, 'text': 'Wrong device ID'}
                    return JsonResponse(data_response)


                for parameter in parameter_list:
                    parameter_value=parameter['value']
                    parameter_name=parameter['name'].lower()
                    try:
                        parameter_info = parameter_info_list.get(name=parameter_name)
                    except ObjectDoesNotExist:
                        continue

                    if parameter_value is not None:
                        column_name="loc_" + parameter_info.name.lower()
                        if not(configuration_check_parameter_value(parameter_value,parameter_info)):
                            fail_counter+=1
                            error_parameter_list.append("1-" + parameter_info.name.upper())
                            continue

                        d = {column_name:parameter_value}
                        parameter_dictionary.update(d)
                        success_counter+=1
                        success_parameter_list.append("1-" + parameter_info.name.upper())
                    else:
                        fail_counter+=1
                        error_parameter_list.append("0-" + parameter_info.name.upper())

                LldevicePdlagParameters.objects.filter(lldevicelist=device_id).update(**parameter_dictionary)

                if fail_counter > 0:
                    user_action_data_short = "New data save with " + str(fail_counter) + " errors"
                    user_action_data_long = "Success: " + str(success_counter) + " Fail: " + str(fail_counter) + " Params: " + ",".join(error_parameter_list)
                    user_add_new_action(request.user.username, "PARAM_SAVE", user_action_data_short,       user_action_data_long, device_id)
                    response_text= "Success: " + str(success_counter) + " Fail: " + str(fail_counter) + " Params: " + ",".join(error_parameter_list)
                else:
                    user_action_data_short = "New data save"
                    user_action_data_long = "Success: " + str(success_counter) + " Fail: " + str(fail_counter) + " Params: " + ",".join(error_parameter_list)
                    user_add_new_action(request.user.username, "PARAM_SAVE", user_action_data_short,user_action_data_long, device_id)
                    response_text = 'ok'

                data_response = {
                    'ok': True,
                    'text': response_text
                }

                return JsonResponse(data_response)

            else:
                return_data = json.loads(request.GET)

    else:
        return HttpResponse('Invalid user')

def configuration_write_parameter_changes(request):
    if request.user.is_authenticated():
        fail_counter=0
        success_counter=0
        device_id = request.GET.get('device_id')

        try:

            parameter_info_list     = LldevicePdlagParameterinfo.objects.all()
            parameter_dictionary    = {}
            error_parameter_list    = []
            success_parameter_list  = []

            for parameter_info in parameter_info_list:
                parameter_value=request.GET.get(parameter_info.name)
                if parameter_value is not None:
                    parameter_name="loc_" + parameter_info.name.lower()
                    if not(configuration_check_parameter_value(parameter_value,parameter_info)):
                        fail_counter+=1
                        error_parameter_list.append("1-" + parameter_info.name.upper())
                        continue

                    d = {parameter_name:parameter_value}
                    parameter_dictionary.update(d)
                    success_counter+=1
                    success_parameter_list.append("1-" + parameter_info.name.upper())
                else:
                    fail_counter+=1
                    error_parameter_list.append("0-" + parameter_info.name.upper())

            LldevicePdlagParameters.objects.filter(lldevicelist=device_id).update(**parameter_dictionary)

            if fail_counter>0:
                user_action_data_short  = "New data save with "+str(fail_counter)+" errors"
                user_action_data_long   = "Success: "+str(success_counter)+ " Fail: "+str(fail_counter)+" Params: "+",".join(error_parameter_list)
                user_add_new_action(request.user.username,"PARAM_SAVE", user_action_data_short,user_action_data_long, device_id)
                return HttpResponse("Success: "+str(success_counter)+" Fail: "+str(fail_counter)+" Params: "+",".join(error_parameter_list))
            else:
                user_action_data_short  = "New data save"
                user_action_data_long   = "Success: "+str(success_counter)+" Fail: "+str(fail_counter)+" Params: "+",".join(error_parameter_list)
                user_add_new_action(request.user.username,"PARAM_SAVE", user_action_data_short,user_action_data_long, device_id)
                return HttpResponse("Ok")

        except Exception as e:
            return HttpResponse("Error: " + e.message)
    else:
        return redirect(reverse('login_page'))


def configuration_write_recalculate_unit_changes(request):
    if request.user.is_authenticated():
        fail_counter = 0
        success_counter = 0
        device_id = request.GET.get('device_id')

        try:
            error_parameter_list    = []
            success_parameter_list  = []

            parameter_dictionary = {}

            # Pressure unit
            field_name_pressure = "loc_pressurerecalculateunit"
            pressure_value = request.GET.get( "PressureRecalculate")
            if pressure_value in measure_return_recalculate_pressure_unit_options():
                success_counter += 1
                parameter_dictionary.update({ field_name_pressure: pressure_value})
                success_parameter_list.append("1-"+field_name_pressure)
            else:
                fail_counter += 1
                error_parameter_list.append("1-"+field_name_pressure)

            # Flow unit
            field_name_flow = "loc_flowrecalculateunit"
            flow_value = request.GET.get("FlowRecalculate")
            if flow_value in measure_return_recalculate_flow_unit_options():
                success_counter += 1
                parameter_dictionary.update({field_name_flow: flow_value})
                success_parameter_list.append("1-"+field_name_flow)
            else:
                fail_counter += 1
                error_parameter_list.append("1-"+field_name_flow)

            # Total flow unit
            field_name_total_flow = "loc_totalflowrecalculateunit"
            total_flow_value = request.GET.get("TotalFlowRecalculate")
            if total_flow_value in measure_return_recalculate_total_flow_unit_options():
                success_counter+=1
                parameter_dictionary.update({field_name_total_flow: total_flow_value})
                success_parameter_list.append("1-"+field_name_total_flow)
            else:
                fail_counter+=1
                error_parameter_list.append("1-"+field_name_total_flow)

            Lldevicelist.objects.filter(id=request.GET.get('device_id')).update(**parameter_dictionary)

            if fail_counter > 0:
                user_action_data_short  = "New unit save with " + str(fail_counter) + " errors"
                user_action_data_long   = "Success: " + str(success_counter) + " Fail: " + str(fail_counter) + " Params: " + ",".join(error_parameter_list)
                user_add_new_action(request.user.username,"UNIT_SAVE", user_action_data_short,user_action_data_long, device_id)
                return HttpResponse("Success: " + str(success_counter) + " Fail: " + str(fail_counter) + " Params: " + ",".join(error_parameter_list))
            else:
                user_action_data_short  = "New unit save"
                user_action_data_long   = "Success: " + str(success_counter) + " Fail: " + str(fail_counter) + " Params: " + ",".join(error_parameter_list)
                user_add_new_action(request.user.username,"UNIT_SAVE", user_action_data_short,user_action_data_long, device_id)
                return HttpResponse("Ok")
        except Exception as e:
            return HttpResponse("Error: " + e.message)
    else:
        return redirect('/leakless-monitor')


def configuration_check_parameter_value(paramvalue, param_info):

    if param_info.type=="STRING":
        # if re.match("^[A-Za-z0-9_-]*$", paramvalue):
        if len(paramvalue)>param_info.max:
            return False
        else:
            return True
    elif param_info.type == "INTEGER":
        if int(paramvalue)>param_info.max or int(paramvalue)<param_info.min:
            return False
        else:
            return True
    elif param_info.type == "DOUBLE":
        if float(paramvalue)>param_info.max or float(paramvalue)<param_info.min:
            return False
        else:
            return True
    elif param_info.type == "ENUM":
        if int(paramvalue)>param_info.max or int(paramvalue)<param_info.min:
            return False
        else:
            return True
    elif param_info.type == "TIME":
        try:
            datetime.strptime(paramvalue, '%H:%M:%S')
            return True
        except ValueError:
            return False
    else:
        return False