/*********************************************************************
 *
 *  $Id: app.ts 32624 2018-10-10 13:23:29Z seb $
 *
 *  Yoctopuce Plugin to ELGATO  StreamDeck
 *
 *
 *********************************************************************/

import { YFunction} from 'yoctolib-esm/yocto_api.js'
import { YRelay } from 'yoctolib-esm/yocto_relay.js'
import { ControllerEnum, StreamDeckAction,YoctopuceDeviceHandler} from '../common_code/yoctopuce_plugin.js'
import { genericSVGIcon } from '../common_code/icons.js'
import { relaySettings } from './relay_settings.js'


export class  StreamDeck_YRelayAction extends StreamDeckAction
 {
   public static readonly  ManagedFunctionType = "relay";
   static  get actionUUID() : string {return "com.yoctopuce."+StreamDeck_YRelayAction.ManagedFunctionType+ ".action"; }
   public  get ManagedFunctionType() { return  StreamDeck_YRelayAction.ManagedFunctionType }
    private  currentSettings : relaySettings = new relaySettings();
    public  relay: YRelay | null =null;
    public  icon : RelayIcon = null as any;
    private lastImage : HTMLImageElement =null as any;

   /*******************************
    * notify the system which Yoctopuce function type is handled by the plugin
    *  must be called at at application start
    *******************************/

   public  static registerFunctionType()
   {
     YoctopuceDeviceHandler.registerFunctionType(StreamDeck_YRelayAction.ManagedFunctionType);
   }

   /*******************************
    * constructor, auttomatically called when a new action is created
    *******************************/

    constructor(uuid:string)
    {   super(uuid);
        YoctopuceDeviceHandler.registerAction(StreamDeck_YRelayAction.ManagedFunctionType,this);
    }

   /*******************************
    * local init
    *******************************/

    public async init()
    {

      this.lastImage = await StreamDeckAction.newImage("relay_action.svg")
   }

   /*******************************
    * return actions settings
    *******************************/

    protected get settings(): relaySettings{return this.currentSettings; }

   /*******************************
    * called when the device linked to the action is appearing
    *******************************/

   protected  async functionArrival(hwdname:string)
   { this.redrawIcon(); }

   /*******************************
    * called when the device linked to the action is disappearing
    *******************************/

   protected  async functionRemoval(hwdname:string)
   { this.redrawIcon(); }

   /*******************************
    * called when the key or rotary button is pressed down
    *******************************/

   public  async onKeyDown(context: any, settings: any, coordinates: any, userDesiredState: any)
     {
         if (this.relay!=null)
         if (await this.relay.isOnline())
             switch  (this.currentSettings.action)
             {   case "MOMENTARY_A":  await this.relay.set_state(YRelay.STATE_A);  break;
                 case "MOMENTARY_B":  await this.relay.set_state(YRelay.STATE_B); break;
             }
     }


   /*******************************
    * called when the key or rotary button is pressed ip
    *******************************/

   public  async onKeyUp(context: any, settings: any, coordinates: any, userDesiredState: any)
      {
        if (this.relay!=null)
           if (await this.relay.isOnline())
               switch  (this.currentSettings.action)
               {   case "MOMENTARY_B":
                   case "A"          : await this.relay.set_state(YRelay.STATE_A); break;
                   case "MOMENTARY_A":
                   case "B"          : await this.relay.set_state(YRelay.STATE_B); break;
                   case "TOGGLE"     : await this.relay.toggle(); break;
                   case "PULSE"      : await this.relay.pulse(this.currentSettings.pulsedelay); break;
               }
     };

   /*******************************
    * called the device current value has changed
    *******************************/

     public valueChanged(source:YRelay , value:String )
     {  if (source==null) return;
         console.log("value changed = "+value);
          if (this.relay == source)
          {
            this.icon.setState(value == "A" ? YRelay.STATE_A : YRelay.STATE_B)
            this.redrawIcon()
          }
     }

   /*******************************
    * redraw the action icon
    *******************************/

   protected async redrawIcon()
     {
         if (this.relay!=null)
             {
                 let online :boolean = await this.relay.isOnline();
                 this.icon.offline   = !online;
                 this.lastImage = new Image();
                 this.lastImage.onload = () =>
                  {
                    this.setBgImage(this.UUID, this.lastImage)
                  }
                 let url:string = this.icon.asURL
                 this.lastImage.src =url ;
             } else this.setBgImage(this.UUID, this.lastImage)

     }

   /*******************************
    * called with local settings
    *******************************/

   public async didReceiveSettings(context: any, settings: any, coordinates: any)
       {
          super.didReceiveSettings(context, settings, coordinates)
          if  (this.currentSettings.hwdName!="")
           {  this.relay = await YRelay.FindRelay(this.currentSettings.hwdName);
              await this.relay.registerValueCallback((source:YFunction,value:string)=>{this.broadcastValueChange(source,value);})
              await this.redrawIcon();
           } else  console.log("relay name not set");
       }

   /*******************************
    * called with global settings
    *******************************/

   public async didReceiveGlobalSettings(context: any,  settings: any) {  }

   /*******************************
    * called when the action is about to be shown
    *******************************/

   public async onWillAppear(context: any,  controller: ControllerEnum,  settings: any, coordinates: any)
      { super.onWillAppear(context, controller, settings, coordinates)
        this.icon=new RelayIcon(72,72);
          console.log("onWillAppear"+JSON.stringify(settings))
        await this.didReceiveSettings(context, settings,  coordinates)
       // this.getGlobalSettings(context);
      }
 }
/*******************************
 * important!
 *******************************/

StreamDeck_YRelayAction.registerFunctionType();


/*******************************
 * icon specific to relays
 *******************************/

export class RelayIcon extends genericSVGIcon
{ private indicatorWidth   : number =60;
  private indicatorHeight  : number=25
  private switchwidth      : number=36
  private thickness        : number =2;
  private  indicatorBg     : SVGRectElement;
  private  indicatorSwitch : SVGRectElement;

  constructor(imgXsize:number,imgYsize:number)
  {   super(imgXsize,imgYsize)

    let radius : number = 3;
    this.indicatorBg   = document.createElementNS("http://www.w3.org/2000/svg", "rect") as SVGRectElement;
    this.indicatorBg.setAttribute("x",((this.width -this.indicatorWidth) /2).toString())
    this.indicatorBg.setAttribute("y",((this.height -this.indicatorHeight)/2).toString())
    this.indicatorBg.setAttribute("width",this.indicatorWidth.toString())
    this.indicatorBg.setAttribute("height",this.indicatorHeight.toString())
    this.indicatorBg.setAttribute("stroke","white");
    this.indicatorBg.setAttribute("fill","black");
    this.indicatorBg.setAttribute("rx",radius.toString());
    this.indicatorBg.setAttribute("ry",radius.toString());
    this.indicatorBg.setAttribute("stroke-width",this.thickness.toString());
    this.svg.appendChild(this.indicatorBg);

    let A :SVGTextElement  =  document.createElementNS("http://www.w3.org/2000/svg","text") as SVGTextElement;
    A.setAttribute("dominant-baseline", "Middle")
    A.setAttribute("text-anchor","start")
    A.setAttribute("font-family","Arial, Helvetica, sans-serif")
    A.setAttribute("font-size",(this.indicatorHeight-4).toString())
    A.setAttribute("x",(3+ (this.width- this.indicatorWidth)/2).toString());
    A.setAttribute("y",(2+this.height/2).toString())
    A.setAttribute("fill","White");
    A.innerHTML="A";
    this.svg.appendChild(A);

    let B :SVGTextElement  =  document.createElementNS("http://www.w3.org/2000/svg","text") as SVGTextElement;
    B.setAttribute("dominant-baseline", "Middle")
    B.setAttribute("text-anchor","end")
    B.setAttribute("font-family","Arial, Helvetica, sans-serif")
    B.setAttribute("font-size",(this.indicatorHeight-4).toString())
    B.setAttribute("x",(-3+ (this.width+ this.indicatorWidth)/2).toString());
    B.setAttribute("y",(2+this.height/2).toString())
    B.setAttribute("fill","black");
    B.innerHTML="B";
    this.svg.appendChild(B);

    this.indicatorSwitch    = document.createElementNS("http://www.w3.org/2000/svg", "rect") as SVGRectElement;
    this.indicatorSwitch.setAttribute("x",(this.thickness+(this.width -this.indicatorWidth) /2).toString())
    this.indicatorSwitch.setAttribute("y",(this.thickness+(this.height -this.indicatorHeight)/2).toString())
    this.indicatorSwitch.setAttribute("width",this.switchwidth.toString())
    this.indicatorSwitch.setAttribute("height",(this.indicatorHeight-2*this.thickness).toString())
    this.indicatorSwitch.setAttribute("stroke","gray");
    this.indicatorSwitch.setAttribute("fill","lightgray");
    this.indicatorSwitch.setAttribute("rx",(radius-this.thickness).toString());
    this.indicatorSwitch.setAttribute("ry",(radius-this.thickness).toString());
    this.indicatorSwitch.setAttribute("stroke-width","2");
    this.svg.appendChild(this.indicatorSwitch);
    this.setState(YRelay.STATE_A)

    this.AddOfflineIndicator();
  }

  public setState(state :number)
  { if (state==YRelay.STATE_B)
  { this.indicatorSwitch.setAttribute("x", (this.thickness+(this.width -this.indicatorWidth) /2).toString())
    this.indicatorBg.setAttribute("fill","greenYellow");
  }
  else
  { this.indicatorSwitch.setAttribute("x", (-this.thickness-this.switchwidth+(this.width +this.indicatorWidth) /2).toString())
    this.indicatorBg.setAttribute("fill","green");

  }

  }

}

// @ts-ignore
