import base64, json, logging #, re
from flask import jsonify, redirect, render_template, Blueprint, flash, session, url_for, request
from common.proto.context_pb2 import (ContextList, Empty, TopologyId, TopologyList 
,DeviceId,DeviceList ,OpticalConfig, OpticalConfigId ,OpticalConfigList)
from common.tools.descriptor.Loader import DescriptorLoader, compose_notifications
from common.tools.grpc.Tools import grpc_message_to_json_string
from common.tools.object_factory.Context import json_context_id
from common.tools.object_factory.Topology import json_topology_id
from context.client.ContextClient import ContextClient
from device.client.DeviceClient import DeviceClient
from service.client.ServiceClient import ServiceClient
from slice.client.SliceClient import SliceClient
from webui.service.main.forms import ContextTopologyForm, DescriptorForm
from .forms import UpdateDeviceForm ,AddTrancseiver ,UpdateInterfaceForm



opticalconfig = Blueprint('opticalconfig', __name__,url_prefix="/opticalconfig")

context_client = ContextClient()
device_client = DeviceClient()
service_client = ServiceClient()
slice_client = SliceClient()

LOGGER = logging.getLogger(__name__)

DESCRIPTOR_LOADER_NUM_WORKERS = 10

@opticalconfig.get("/")
def home() :
    config=[]
    deviceId= DeviceId()
    
    if 'context_uuid' not in session or 'topology_uuid' not in session:
        flash("Please select a context!", "warning")
        return redirect(url_for("main.home"))
    context_uuid = session['context_uuid']
    topology_uuid = session['topology_uuid']
   
    context_client.connect()
    opticalConfig_list:OpticalConfigList = context_client.GetOpticalConfig(Empty())
    logging.info("myconfigList  %s",opticalConfig_list)

    for configs in opticalConfig_list.opticalconfigs:

        value=json.loads(configs.config) if type(configs.config)==str else configs.config
        value["channels_number"]=len(value['channels'])
      
        # value['operationalMode']=value['operational-mode']
        # value['targetOutputPower']=value['target-output-power']
        value['opticalconfig_id']=configs.opticalconfig_id
        # value['line_port']=value["line-port"]
        
        config.append(value)
     
    logging.info("opticalConfig  %s",config)
   
    context_client.close()

    return render_template(
        'opticalconfig/home.html', config=config)
@opticalconfig.route('<path:config_uuid>/detail',methods=['GET'])    
def show_details(config_uuid):
        opticalconfigId=OpticalConfigId()
        opticalconfigId.opticalconfig_uuid=config_uuid
        device_details=[]
        context_client.connect()
        response = context_client.SelectOpticalConfig(opticalconfigId)
        context_client.close()
        LOGGER.info("response %s",response)
        opticalConfig = OpticalConfig()
        opticalConfig.CopyFrom(response)
        
        config =json.loads(opticalConfig.config)
        LOGGER.info("config details %s",config)
        interfaces=config["interfaces"]
        new_config={}
      
        for channel in config['channels'] :
            
            new_config["name"]=channel['name']
            new_config['operationalMode']=channel['operational_mode'] if 'operational_mode' in channel else ''
            new_config['targetOutputPower']=channel['target_output_power'] if 'target_output_power' in channel else ''
            new_config["frequency"]=channel['frequency'] if 'frequency' in channel else ''
            new_config['line_port']=channel["line-port"] if 'line-port' in channel else ''
         
            device_details.append(new_config)
        LOGGER.info("config details %s",device_details)    
        return render_template('opticalconfig/details.html', device=device_details,config_id=config_uuid,interfaces=interfaces)
@opticalconfig.route('<path:config_uuid>/<path:channel_name>/update', methods=['GET', 'POST'])
def update(config_uuid,channel_name):
    form = UpdateDeviceForm()

    opticalconfigId=OpticalConfigId()
    opticalconfigId.opticalconfig_uuid=config_uuid
    context_client.connect()
    response = context_client.SelectOpticalConfig(opticalconfigId)
    context_client.close()
    LOGGER.info("response %s",response)
    opticalconfig = OpticalConfig()
    opticalconfig.CopyFrom(response)
    config =json.loads(opticalconfig.config)
    new_config={}
    for channel in config['channels']:
        if (channel["name"] == channel_name):
            new_config=channel
            form.frequency.default = channel["frequency"]
            form.operational_mode.default=channel["operational-mode"]
            form.power.default=channel["target-output-power"]
            form.line_port.choices = [("","")]
            
    for transceiver in config["transceivers"]['transceiver']:
        
        form.line_port.choices.append((transceiver,transceiver))
    # listing enum values

    if form.validate_on_submit():
       
        new_config["target-output-power"] =form.power.data if form.power.data != '' else  new_config['target-output-power']
        new_config["frequency"]=form.frequency.data if form.frequency.data != '' else new_config['frequency']
        new_config["operational-mode"]=form.operational_mode.data if form.operational_mode.data != '' else new_config['operational-mode']
        new_config["line-port"]=form.line_port.data if form.line_port.data != '' else new_config['line-port']

        opticalconfig.config =json.dumps(new_config)
        LOGGER.info("myconfig copied %s",opticalconfig)
        try:
            device_client.connect()
            device_client.ConfigureOpticalDevice(opticalconfig)
            device_client.close()
            flash(f' device  was updated.', 'success')
            return redirect(url_for('opticalconfig.show_details',config_uuid=config_uuid))
        except Exception as e: # pylint: disable=broad-except
             flash(f'Problem updating the device. {e}', 'danger')  
    return render_template('myabout/update.html', device=response, form=form, submit_text='Update Device',channel_name=channel_name)
@opticalconfig.route('<path:config_uuid>/<path:interface_name>/update_interface', methods=['GET', 'POST'])
def update_interface (config_uuid,interface_name):
    form = UpdateInterfaceForm()
    opticalconfigId=OpticalConfigId()
    opticalconfigId.opticalconfig_uuid=config_uuid
    context_client.connect()
    response = context_client.SelectOpticalConfig(myid)
    context_client.close()
    LOGGER.info("response %s",response)
    opticalconfig = OpticalConfig()
    opticalconfig.CopyFrom(response)
    config =json.loads(opticalconfig.config)
    new_config={}
    if form.validate_on_submit():
        new_config["ip"]=form.ip.data if form.ip.data != "" else config["interfaces"]["interface"]["ip"]
        new_config["prefix-length"]=form.prefix_length.data if form.prefix_length.data != "" else config["interfaces"]["interface"]["prefix-length"]
        new_config["name"]=config["interfaces"]["interface"]["name"]
        new_config["enabled"]=config["interfaces"]["interface"]["enabled"]
      
        opticalconfig.config=json.dumps({"update_interface":new_config})
        try:
                device_client.connect()
                device_client.ConfigureOpticalDevice(opticalconfig)
                device_client.close()
                flash(f' device  was updated.', 'success')
                return redirect(url_for('opticalconfig.show_details',config_uuid=config_uuid))
        except Exception as e: # pylint: disable=broad-except
                flash(f'Problem updating the device. {e}', 'danger')      
    return render_template('opticalconfig/update_interface.html',
                           device=response, form=form, submit_text='Update interface',interface_name=interface_name)    
    
@opticalconfig.route('<path:config_uuid>/add_transceiver', methods=['GET','POST'])
def add_transceiver (config_uuid):
    config={}
    addtrancseiver=AddTrancseiver()
    opticalconfigId=OpticalConfig()
    opticalconfigId.opticalconfig_uuid=config_uuid
    context_client.connect()
    response = context_client.SelectOpticalConfig(opticalconfigId)
    context_client.close()
    opticlConfig=OpticalConfig()
    opticlConfig.CopyFrom(response)
    if addtrancseiver.validate_on_submit():
        config["add_transceiver"]=addtrancseiver.transceiver.data
        opticlConfig.config=json.dumps(config)
       
        try:
            device_client.connect()
            device_client.ConfigureOpticalDevice(opticlConfig)
            device_client.close()
            flash(f' device  was updated.', 'success')
            return redirect(url_for('opticalconfig.update',config_uuid=config_uuid))
        except Exception as e: # pylint: disable=broad-except
             flash(f'Problem updating the device. {e}', 'danger')  
    return render_template('opticalconfig/add_transceiver.html',form=addtrancseiver, submit_text='Add Trancseiver')         
        
        
        
    