<script>
import ControllerState from "../components/ControllerState.vue"
//import ControllerMoving from "../components/ControllerMoving.vue"
import ControllerMovingNew from "../components/ControllerMovingNew.vue"
import ControllerConsole from "../components/ControllerConsole.vue"
import ControllerGCode from "../components/ControllerGCode.vue"
import ControllerSettings from "../components/ControllerSettings.vue"
import CamerasSettings from "../components/CamerasSettings.vue"
import CVSettings from "../components/CVSettings.vue"
import HeadsSettings from "../components/HeadsSettings.vue"
import PumpSettings from "../components/PumpSettings.vue"
import NozzlesSettings from "../components/NozzlesSettings.vue"
import NozzlesHolderSettings from "../components/NozzlesHolderSettings.vue"
import BasketSettings from "../components/BasketSettings.vue"
import ParkingSettings from "../components/ParkingSettings.vue"
import FeedersSettings from "../components/FeedersSettings.vue"
import PCBTableSettings from "../components/PCBTableSettings.vue"
import Projects from "../components/Projects.vue"

import Loading from "../components/Loading.vue"
import Vializer3D from "../components/Vializer3D.vue"
import Window from "../components/Window.vue"

import { confirm, alert } from '../js/dialogs.js'
import { DialogWrapper } from 'vue3-promise-dialog'

import moveMixin from '../js/move_mixin.js'
import pnpMixin from '../js/pnp_mixin.js'
import deepMerge from '../js/deep_merge.js'

import { toRaw } from 'vue';

export default {
  mixins: [moveMixin, pnpMixin, deepMerge],
  components: {
    Loading, DialogWrapper, Window, Vializer3D, ControllerState, /*ControllerMoving,*/ ControllerMovingNew, ControllerConsole, ControllerGCode, ControllerSettings, CamerasSettings, CVSettings, HeadsSettings, PumpSettings, NozzlesSettings, NozzlesHolderSettings, BasketSettings, ParkingSettings, FeedersSettings, PCBTableSettings, Projects
  },
  data() {
    return {
      tab: 0,
      tabSettings: 0,
      showWindow: [false, false, false, false],
      timerId: this.timerId,

      consoleLog: '',
      command: this.command,
      request: this.request,
      
      gCodeProcess: {
        stopFlag: false,
        pauseFlag: false,
      },

      pnpProcessing: {
        runFlag: false,
        stopFlag: false,
        pauseFlag: false,
        element: null,
        message: ""
      },

      camsViewSMDCase: {
        case: '',
        rotate: 0.0
      },

      camsViewParams: [
	      {'raw':1, 'cv':0, 'ppmm':10, 'grid':1, 'marker':0},
	      {'raw':1, 'cv':0, 'ppmm':10, 'grid':1, 'marker':0}
      ],
      CVLikeMachineView: false,

      CVResult:[{}, {}],

      machineState: {
        status: 'Not connected',
        pos: {x:0, y:0, z:0, a:0},
        settings: {},
        info: {},
        gc: []
      },

      loading: false,

      //topCamNozzlePos: 0, // 0 - Nozzle position; 1 - Top camera position
      movingOptions: {
        topCamNozzlePos: 0, // 0 - Nozzle position; 1 - Top camera position
        stepSize: 10.0,
        feedRateXYZ: 2000,
        rotateStep: 0.125,
        feedRateA: 500,
      },

      settings: {
        machineOffsets: {x:1.0, y:1.0, z:1.0, a:0.0}, // Offset after homming                      !!! GUI !!!
        cams: [
          {
              id: "0",
              name: 'Top',
              size: {
                width: 800,
                height: 600
              },

              undistort: {
                type: 0,
                distortion_f: 0.0,
                calibration: {
                  matrix: [[5.43196224e+05, 0.00000000e+00, 2.49972745e+03], [0.00000000e+00, 5.24402144e+05, 1.89918430e+03], [0.00000000e+00, 0.00000000e+00, 1.00000000e+00]],
                  distortion: [[-1.15271070e+01,  1.37230942e-03, -1.12470987e-03, -1.96992455e-02, 2.66238632e-08]]
                },
              },

              image_transform: {
                rotation: 0,
                scale_x: 1.0,
                scale_y: 1.0
              },
              
              ppmm: 10,
              pos: {x:0, y:0, z:0},
              offset: {x:0, y:0},
              lightOn: 'M72',
              lightOff: 'M71'
          },
          {
              id: "1",
              name: 'Bottom',
              size: {
                width: 800,
                height: 600
              },

              undistort: {
                type: 0,
                distortion_f: 0.0,
                calibration: {
                  matrix: [[5.43196224e+05, 0.00000000e+00, 2.49972745e+03], [0.00000000e+00, 5.24402144e+05, 1.89918430e+03], [0.00000000e+00, 0.00000000e+00, 1.00000000e+00]],
                  distortion: [[-1.15271070e+01,  1.37230942e-03, -1.12470987e-03, -1.96992455e-02, 2.66238632e-08]]
                },
              },

              image_transform: {
                rotation: 0,
                scale_x: 1.0,
                scale_y: 1.0
              },

              ppmm: 10,
              pos: {x:0, y:0, z:0},
              offset: {x:0, y:0},
              lightOn: 'M82',
              lightOff: 'M81'
          }
        ],
        cv: [
          {
            name: 'Top',
            contrast: 1.0,
            brightness: 0.0,
            blur: [1, 1],
            adaptiveThreshold_blockSize: 11,
            adaptiveThreshold_C: 2,
            objects: {
              circle: {"r-min": 1.5, "r-max": 2, "dist-min": 7},
              rectangle: {"w-min": 2, "w-max": 8.0, "h-min": 2, "h-max": 8.0},
            },
            pauseBefore: 0,
          },
          {
            name: 'Bottom',
            contrast: 1.0,
            brightness: 0.0,
            blur: [1, 1],
            adaptiveThreshold_blockSize: 799,
            adaptiveThreshold_C: 27,
            objects: {
              contour: {"w-min": 0.2, "w-max": 20.0, "h-min": 0.2, "h-max": 20.0},
              circle: {"r-min": 1.5, "r-max": 4, "dist-min": 10},
            },
            pauseBefore: 0,
          }
        ],

        basket: {
          pos: {x:0, y:0, z:0}
        },

        parking: {
          pos: {x:0, y:0, z:0}
        },

        table: {
          pos : {x:0, y:0, z: 0}
        },

        heads: [
          {
            id:0,
            name: "Head 1",
            safePosZ: 20,
            valveOn: 'M32',
            valveOff:'M31',
            inGC: 'V1',
            pauseBeforeOn: 0,
            pauseAfterOn: 0,
            pauseBeforeOff: 0,
            pauseAfterOff: 0,
            nozzle: 0
          }
        ],

        pump: {
          On: 'M42',
          Off: 'M41',
          inGC: 'V2',
        },

        nozzles: [
          {
            id: 0,
            name: "Nozzle 1",
            caption: "",
            calibrationData: [
              {a:0.0,   dx:0.0, dy:0.0},
              {a:0.125, dx:0.0, dy:0.0},
              {a:0.25,  dx:0.0, dy:0.0},
              {a:0.375, dx:0.0, dy:0.0},
              {a:0.5,   dx:0.0, dy:0.0},
              {a:0.625, dx:0.0, dy:0.0},
              {a:0.75,  dx:0.0, dy:0.0},
              {a:0.875, dx:0.0, dy:0.0}
            ]
          },
        ],

        nozzlesHolder: {
          places: [
            {id: 1, name: 'Place 1', nozzleId:-1, points:[{x:0, y:0, z:0}, {x:0, y:0, z:0}, {x:0, y:0, z:0}], feed: 100},
            {id: 2, name: 'Place 2', nozzleId:-1, points:[{x:0, y:0, z:0}, {x:0, y:0, z:0}, {x:0, y:0, z:0}], feed: 100},
            {id: 3, name: 'Place 3', nozzleId:-1, points:[{x:0, y:0, z:0}, {x:0, y:0, z:0}, {x:0, y:0, z:0}], feed: 100},
            {id: 4, name: 'Place 4', nozzleId:-1, points:[{x:0, y:0, z:0}, {x:0, y:0, z:0}, {x:0, y:0, z:0}], feed: 100},
            {id: 5, name: 'Place 5', nozzleId:-1, points:[{x:0, y:0, z:0}, {x:0, y:0, z:0}, {x:0, y:0, z:0}], feed: 100}
          ]
        },
      },
      
      cases: [
        {
          name: "",
          src: ""
        },


        {
          name: "R0402",
          src: "cases/R0402.svg"
        },
        {
          name: "R0603",
          src: "cases/R0603.svg"
        },
        {
          name: "R0805",
          src: "cases/R0805.svg"
        },
        {
          name: "R1206",
          src: "cases/R1206.svg"
        },
        {
          name: "R1210",
          src: "cases/R1210.svg"
        },
        {
          name: "R1812",
          src: "cases/1812.svg"  //!!!
        },
        {
          name: "R2010",
          src: "cases/2010.svg"  //!!!
        },
        {
          name: "R2220",
          src: "cases/2220.svg"  //!!!
        },
        {
          name: "R2512",
          src: "cases/2512.svg"  //!!!
        },


        {
          name: "C0402",
          src: "cases/C0402.svg"
        },
        {
          name: "C0603",
          src: "cases/C0603.svg"
        },
        {
          name: "C0805",
          src: "cases/C0805.svg"
        },
        {
          name: "C1206",
          src: "cases/C1206.svg"
        },



        {
          name: "SOD-923",
          src: "cases/sod923.svg"
        },
        {
          name: "SOD-723",
          src: "cases/sod723.svg"
        },
        {
          name: "SOD-523",
          src: "cases/sod523.svg"
        },
        {
          name: "SOD-323",
          src: "cases/SOD-323.svg"
        },
        {
          name: "SOD-123",
          src: "cases/sod123.svg"
        },
        {
          name: "SOD-123F",
          src: "cases/sod123f.svg"
        },
        {
          name: "SOD-123FL",
          src: "cases/SOD-123FL.svg"
        },
        {
          name: "SOD-123W",
          src: "cases/sod123w.svg"
        },
        {
          name: "SMA",
          src: "cases/SMA.svg"
        },
        {
          name: "SMB",
          src: "cases/SMB.svg"
        },
        {
          name: "SMC",
          src: "cases/smc.svg"
        },


        {
          name: "LED-0603",
          src: "cases/LED0603.svg"
        },
        {
          name: "LED-0805",
          src: "cases/LED0805.svg"
        },


        {
          name: "SOT-23",
          src: "cases/SOT-23.svg"
        },
        {
          name: "SOT-23-5",
          src: "cases/SOT-23-5.svg"
        },
        {
          name: "SOT-23-6",
          src: "cases/SOT-23-6.svg"
        },
        {
          name: "SOT-AMS-1117-2.5",
          src: "cases/SOT-AMS-1117-2.5.svg"
        },
        {
          name: "TO-263-2",
          src: "cases/TO-263-2.svg"
        },


        {
          name: "PDFN-8-L5.2W5.9",
          src: "cases/PDFN-8-L5.2W5.9.svg"
        },
        {
          name: "PDFN-8-L5.5W5.2",
          src: "cases/PDFN-8-L5.5W5.2.svg"
        },


        {
          name: "SOP-8",
          src: "cases/SOP-8.svg"
        },
        {
          name: "SOIC-8",
          src: "cases/SOIC-8.svg"
        },
        {
          name: "SOP-16",
          src: "cases/SOP-16.svg"
        },


        {
          name: "TSSOP-8",
          src: "cases/TSSOP-8.svg"
        },

        {
          name: "TSSOP-16",
          src: "cases/TSSOP-16.svg"
        },

        {
          name: "TSSOP-20",
          src: "cases/TSSOP-20.svg"
        },


        {
          name: "LQFP-48",
          src: "cases/LQFP-48.svg"
        },
        {
          name: "LQFP-64",
          src: "cases/LQFP-64.svg"
        },

        {
          name: "BTS7960B",
          src: "cases/BTS7960B.svg"
        },

        {
          name: "OSC-SMD-4P3225",
          src: "cases/OSC-SMD-4P3225.svg"
        },        

      ],

      feeders: [],

      project: {
        name: 'New Project',
        feeders: [],
        elements: [],
        pcb: {
          pos: {x:0, y:0, z:1.6}
        } 
      },

      projects_list: []

    }
  },
  computed: {
    portConnection() {
      return this.$root.serialPortHandler
    },
    portIsOpened() {
      if (this.portConnection) {
        if (this.portConnection.isOpened == true) {
          return true
        }
      }
    },

    videoSrc() {
      let result = []
      let number = 0
      for (let camCfg of this.camsViewParams) {
        let url = `http://localhost:5000/video_feed/${number}/${camCfg['raw']}/${camCfg['cv']}/${camCfg['ppmm']}/${camCfg['grid']}/${camCfg['marker']}?${Date.now()}`
        number += 1
        result.push(url)
      }
      return result
    },

    controlsEnabled() {
      return ((this.machineState.status == 'Idle') && (this.pnpProcessing.runFlag == false))
    },
    controlsEnabledUnderAlarm() {
      return ( ( (this.machineState.status == 'Idle') || (this.machineState.status == 'Alarm') || (this.machineState.status == 'Home') ) && (this.pnpProcessing.runFlag == false) )
    },

    pumpState() {
      let result = false
      if (typeof this.machineState.info.GC != 'undefined') {
        result = this.machineState.info.GC.indexOf(this.settings.pump.inGC) > -1
      }
      return result
    },

    valvesState() {
      let result = [false]
      if (typeof this.machineState.info.GC != 'undefined') {
        for (let n in this.settings.heads) {
          result[n] = this.machineState.info.GC.indexOf(this.settings.heads[n].inGC) > -1
        }
      }
      return result
    },

    lightsState() {
      let result = [false, false]
      if (typeof this.machineState.info.GC != 'undefined') {
        for (let n=0; n<2; n ++) {
          result[n] = this.machineState.info.GC.indexOf('L'+(n+1)) > -1
        }
      }
      return result
    },

    machinePos() {
      let x = parseFloat(this.machineState.pos.x) + this.settings.machineOffsets.x
      let y = parseFloat(this.machineState.pos.y) + this.settings.machineOffsets.y
      let z = parseFloat(this.machineState.pos.z) + this.settings.machineOffsets.z
      let a = parseFloat(this.machineState.pos.a) + this.settings.machineOffsets.a

      return {x:x.toFixed(3), y:y.toFixed(3), z:z.toFixed(3), a:a.toFixed(3)}
    },

    cvParams() {
      // Convert CV Params in mm to pixel for all cameras
      let result = []
      for (let n in this.settings.cv) {
        //let objects = Object.assign(this.settings.cv[n].objects)
        //let objects = JSON.parse(JSON.stringify(this.settings.cv[n].objects));
        let objects = structuredClone(toRaw(this.settings.cv[n].objects))
        for (let objName in objects) {
          for (let key in objects[objName]) {
            objects[objName][key] = Math.round(objects[objName][key] * this.settings.cams[n].ppmm)
          }
        }
        objects = Object.assign(objects, {"text": false, "img_type": this.CVLikeMachineView?1:0})
        result.push(objects)
      }
      return result
    }
  },

  methods: {
    fetch_execute: async function (url, options, callbackOK, callbackError) {
      this.loading = true
      try {
        let response = await fetch(url, options)
        let result = await response.json()
        if (callbackOK) {
          callbackOK(result)
        }
      }
      catch (error) {
        if (callbackError) {
          callbackError(error)
        }
      }
      finally {
        this.loading = false
      }
    },
/*
    deepMerge(obj1, obj2) {
      const merged = Object.assign(obj1)
      for (const key in obj2) {
        if (obj2.hasOwnProperty(key)) {
          if (obj1[key] && typeof obj1[key] === 'object' && typeof obj2[key] === 'object') {
            merged[key] = this.deepMerge(obj1[key], obj2[key])
          } else {
            merged[key] = obj2[key]
          }
        }
      }
      return merged
    },
  */

    loadMachineState() {
      this.sendCommands(['$I', '$$', '$G', '?'])
    },

    consoleLogAppend(log) {
      this.consoleLog = this.consoleLog + log + '\n'
    },

    changeCamParam(params) {
      this.camsViewParams[params.number] = {'raw':params.raw, 'cv':params.cv, 'ppmm':params.ppmm, 'grid':params.grid, 'marker':params.marker}
    },

    toggleCamParam(params) {
      if (this.showWindow[params.number] == true) {
        this.closeCam(params.number)
      } else {
        this.changeCamParam(params)
        this.openCam(params.number)
      }
    },

    toggleCam(number) {
      this.toggleCamParam({'number': number, 'raw':0, 'cv':0, 'ppmm':10, 'grid':1, 'marker':0})
    },

    openCam(number) {
      this.showWindow[number] = true
    },

    closeCam(number) {
      let img = this.$refs['cam_feed' + number]
      img.src = "" // clean image src to stop loading video feed. If you simply remove <img> tag video feed will continues to loading
      this.showWindow[number] = false

      if (number == 0) { // If Top camera view closing then clear SMD Case. SMD Case uses when element plase on board
        this.camsViewSMDCase = {case: '', rotate: 0.0}
      }
    },

    toggleCV(number) {
      if (this.showWindow[(number+2)] == true) {
        this.closeCV(number)
      } else {
        this.openCV(number)
      }
    },

    lightOn(number) {
      let cmd = this.settings.cams[number].lightOn
      this.sendCommandUI(cmd)
    },
    lightOff(number) {
      let cmd = this.settings.cams[number].lightOff
      this.sendCommandUI(cmd)
    },
    toggleLight(number) {
      if (this.lightsState[number] == false) {
        this.lightOn(number)
      } else {
        this.lightOff(number)
      }
    },

    getCV(number) {
      let url = 'http://localhost:5000/cv/'+number

      let postdata = this.cvParams[number]
      this.fetch_execute(url, { method: 'POST', credentials: 'same-origin', cache: 'no-cache', headers: {'Content-Type': 'application/json;charset=utf-8'}, body: JSON.stringify(postdata) },
          (data)=>{
            this.CVResult[number] = data
            console.log(data.objects)
          },
          (error)=>{
              console.log(error)
              alert(error, 'Error', 'error')
          }
      );
    },

    openCV(number) {
      this.showWindow[(number+2)] = true
      this.getCV(number)
    },

    closeCV(number) {
      this.showWindow[(number+2)] = false
    },

    toggleMoviePanel() {
      if (this.showWindow[4] == true) {
        this.closeMoviePanel()
      } else {
        this.openMoviePanel()
      }
    },
    openMoviePanel() {
      this.showWindow[4] = true
    },
    closeMoviePanel() {
      this.showWindow[4] = false
    },

    gCodeRun(commands) {
      this.sendCommands(commands, true)
    },

    gCodeStop() {
      this.gCodeProcess.pauseFlag=false
      this.gCodeProcess.stopFlag=true
    },

    gCodePause() {
      this.gCodeProcess.pauseFlag=!this.gCodeProcess.pauseFlag
    },

    pnpProcessingRun() {
      this.pnpProcessing.pauseFlag=false
      this.pnpProcessing.stopFlag=false
      this.pnpProcessing.runFlag=true
    },
    pnpProcessingPause() {
      this.pnpProcessing.pauseFlag=!this.pnpProcessing.pauseFlag
    },
    pnpProcessingResume() {
      this.pnpProcessing.pauseFlag=false
    },
    pnpProcessingStop() {
      this.pnpProcessing.stopFlag=true
    },
    pnpProcessingReset() {
      this.pnpProcessing.pauseFlag=false
      this.pnpProcessing.stopFlag=false
      this.pnpProcessing.runFlag=false
    },

    moveOnClick(event) {
      if (this.controlsEnabled == true) {
        let centerX = event.srcElement.width / 2
        let centerY = event.srcElement.height / 2

        let camNumber = event.srcElement.id
        let dX
        let dY
  
        if (camNumber == 0) {
          dX = event.offsetX - centerX
          dY = centerY - event.offsetY
        } else {
          dX = event.offsetX - centerX
          dY = event.offsetY - centerY
        }

        let ppmm = this.settings.cams[camNumber].ppmm
        let dXmm = Math.round((dX / ppmm) * 1000) / 1000
        let dYmm = Math.round((dY / ppmm) * 1000) / 1000

        /*
        let newX = this.machineState.pos.x - dXmm
        let newY = this.machineState.pos.y + dYmm
        */
      
        let command = `$J=G21G91X${dXmm}Y${dYmm}F500`
        this.sendCommandUI(command)
      }
    },

    calibrate(number) {
      let url = 'http://localhost:5000/calibration/'+number+'?' + Date.now()

      this.fetch_execute(url, { method: 'GET', credentials: 'same-origin', cache: 'no-cache' },
          (data)=>{
              if (data.result == 'OK') {
                  this.settings.cams[number].calibration = data
                  alert("Calibration complete successfully. Don't forget to apply settings.", "Calibration", 'success')
              } else {
                  alert(data.msg, 'Error', 'error')
              }
          },
          (error)=>{
              console.log(error)
              alert(error, 'Error', 'error')
          }
      );
    },

    loadSettings() {
      let url = 'http://localhost:5000/settings?' + Date.now()

      this.fetch_execute(url, { method: 'GET', credentials: 'same-origin', cache: 'no-cache' },
          (data)=>{
            this.settings = this.deepMerge(this.settings, data)
            //this.settings = data
          },
          (error)=>{
              console.log(error)
              alert(error, 'Error', 'error')
          }
      );
    },

    applaySettings() {
      let url ="http://localhost:5000/settings"
      let postdata = this.settings

      this.fetch_execute(url, { method: 'POST', credentials: 'same-origin', cache: 'no-cache', headers: {'Content-Type': 'application/json;charset=utf-8'}, body: JSON.stringify(postdata) },
          (data)=>{
              if (data.result == 'OK') {
                  alert('Settings applied successfully', 'Settings', 'success')
              } else {
                  if (data.error) {
                      alert(data.error, 'Error', 'error')
                  } else {
                      alert('Unexpected Error!', 'Error', 'error')
                  }
              }
          },
          (error)=>{
              console.log(error)
              alert(error, 'Error', 'error')
          }
      );
    },

    setFeedersFromProject() {
      this.feeders = this.project.feeders
      confirm('Feeders set from current project applied as default feeder set, but settings is not saved yet. Do You want to save and apply settings?', 'Confirm').then((res)=> {
          if (res == true) {
            this.applaySettings()
          }
      })
    },

    newProject() {
      this.project = {
          name: 'New Project',
          feeders: [],
          elements: [],
          pcb: {
            pos: {x:0, y:0, z:0}
          } 
      }
    },

    loadProject() {
      this.loadJSON('projects', this.project.name, 'project')
    },

    saveProject() {
      this.saveJSON('projects', this.project.name, this.project)
      setTimeout(() => { this.loadProjectsList() }, 1000)
    },

    renameProject(event) {
      let url = `http://localhost:5000/json/rename/projects/${event.name}/${event.newName}`

      this.fetch_execute(url, { method: 'GET', credentials: 'same-origin', cache: 'no-cache' },
          (data)=>{
            this.loadProjectsList()
          },
          (error)=>{
              console.log(error)
              alert(error, 'Error', 'error')
          }
      );
    },

    deleteProject(projectName) {
      let url = `http://localhost:5000/json/delete/projects/${projectName}`

      this.fetch_execute(url, { method: 'GET', credentials: 'same-origin', cache: 'no-cache' },
          (data)=>{
            this.loadProjectsList()
          },
          (error)=>{
              console.log(error)
              alert(error, 'Error', 'error')
          }
      );
    },

    loadProjectsList() {
      let url = 'http://localhost:5000/json-list/projects?' + Date.now()

      this.fetch_execute(url, { method: 'GET', credentials: 'same-origin', cache: 'no-cache' },
          (data)=>{
            this.projects_list = data.result
          },
          (error)=>{
              console.log(error)
              alert(error, 'Error', 'error')
          }
      );
    },

    loadJSON(folder, file, dataname) {
      //let url ="http://localhost:5000/json/" + folder + "/" + file + '?' + Date.now()
      let url ="http://localhost:5000/json"
      if (folder !== '') {
        url = url + '/' +folder
      }
      url = url + "/" + file

      this.fetch_execute(url, { method: 'GET', credentials: 'same-origin', cache: 'no-cache' },
          (data)=>{
            this[dataname] = data.result
          },
          (error)=>{
              console.log(error)
              alert(error, 'Error', 'error')
          }
      );
    },
  
    saveJSON(folder, file, dataset) {
      let url ="http://localhost:5000/json"
      if (folder !== '') {
        url = url + '/' +folder
      }
      url = url + "/" + file

      this.fetch_execute(url, { method: 'POST', credentials: 'same-origin', cache: 'no-cache', headers: {'Content-Type': 'application/json;charset=utf-8'}, body: JSON.stringify(dataset) },
          (data)=>{
              if (data.result == 'OK') {
                  alert('File "' + file + '" saved successfully', 'Settings', 'success')
              } else {
                  if (data.error) {
                      alert(data.error, 'Error', 'error')
                  } else {
                      alert('Unexpected Error!', 'Error', 'error')
                  }
              }
          },
          (error)=>{
              console.log(error)
              alert(error, 'Error', 'error')
          }
      );
    },

    setSMDCase(smdCase) {
      this.camsViewSMDCase = smdCase
      this.drawTopCamCanvas()
    },

    // Draw grid on view of top camera
    drawTopCamCanvas() {
      if (this.$refs['camCanvas0']) {
        let canvas = this.$refs['camCanvas0']
        let ctx = canvas.getContext('2d')
        if (ctx) {
          ctx.globalAlpha = 0.7
          let width = canvas.width
          let height = canvas.height
          let lineLong = canvas.width / 2
          let lineColor = "#239b56"
          let lineWidt = 1
          let cx = width / 2
          let cy = height / 2
          //let a = 2*Math.PI * (parseFloat(this.machineState.pos.a) + parseFloat(this.camsViewSMDCase.rotate))
          let a = 2*Math.PI * parseFloat(this.camsViewSMDCase.rotate)
          let ppmm = parseFloat(this.settings.cams[0].ppmm)

          let caseName = this.camsViewSMDCase.case //"SOT-23"

          // Clear Canvas
          ctx.clearRect(0, 0, width, height)

          // Rotate canvas
          ctx.translate(cx, cy)
          ctx.rotate(-a)
          ctx.translate(-cx, -cy)

          // Draw lines
          ctx.beginPath()
          ctx.moveTo(cx-lineLong/2, cy)
          ctx.lineTo(cx+lineLong/2, cy)
          ctx.strokeStyle = lineColor
          ctx.lineWidth = lineWidt

          // Draw circle
          ctx.arc(cx, cy, 0.6 * ppmm, 0, 2*Math.PI)

          // Renter canvas
          ctx.stroke()

          // Rotate canvas back (after rendering)
          ctx.translate(cx, cy)
          ctx.rotate(a)
          ctx.translate(-cx, -cy)

          // Draw case if caseName is set
          for (let SMDcase of this.cases) {
            if (SMDcase.name == caseName) {

              const img = new Image();
              img.src = SMDcase.src
              
              img.onload = ()=> {
                  let cx = width / 2
                  let cy = height / 2
                  //let ppmm = 10

                  let defaultDPI = 96.0
                  let defaultPPMM = defaultDPI / 25.4
                  let newWidth = img.width * (ppmm/defaultPPMM)
                  let newHeight = img.height * (ppmm/defaultPPMM)

                  let imgX = cx - newWidth / 2
                  let imgY = cy - newHeight / 2

                  // Rotate canvas
                  ctx.translate(cx, cy)
                  ctx.rotate(-a)
                  ctx.translate(-cx, -cy)

                  // Draw SVG on Canvas
                  ctx.drawImage(img, imgX, imgY, newWidth, newHeight)

                  // Rotate canvas back (after rendering)
                  ctx.translate(cx, cy)
                  ctx.rotate(a)
                  ctx.translate(-cx, -cy)


                  // Renter canvas
                  ctx.stroke()                        
              };
            }
          }
        }
      }
    }

  },

  mounted() {
    this.loadSettings()
    this.loadJSON('', 'feeders', 'feeders')
    this.loadProjectsList()
  },
  unmounted() {

  },

  watch: {
    async portIsOpened(newValue) {
      if (newValue) {
        this.loadMachineState()

        setTimeout(() => {
          let pos = parseFloat(this.machineState.pos.x) + parseFloat(this.machineState.pos.y) + parseFloat(this.machineState.pos.z)
          if (pos == 0) {
            confirm('Are You wish to dispatch Machine to Home & Reset Zero?', 'Confirm').then((res)=> {
              if (res == true) {
                this.controllerMove('HomeResetZero')
              }
            })
          }
        }, 300)
      } else {
        this.machineState.status = 'Not connected'
      }
    },

    showWindow: {
      handler(newValue, oldValue) {
        if (this.showWindow[0] == 1) {
          setTimeout(() => { this.drawTopCamCanvas() }, 200)
        }
      },
      deep: true
    },

    machineState: {
      handler(newValue, oldValue) {
        clearTimeout(this.timerId)
        this.timerId = setTimeout(() => { this.drawTopCamCanvas() }, 200)
      },
      deep: true
    }


  }
}
</script>

<template>
<div>

  <div class="float-end tool-buttons">
    <button :class="'btn btn-sm btn-outline-secondary p-0 ps-1 pe-1 m-0 me-1' + (showWindow[2]==true?' active':'')" @click="toggleCV(0)">👁🠟</button>
    <button :class="'btn btn-sm btn-outline-secondary p-0 ps-1 pe-1 m-0 me-1' + (showWindow[3]==true?' active':'')" @click="toggleCV(1)">👁🠝</button>
    <button :class="'btn btn-sm btn-outline-secondary p-0 ps-1 pe-1 m-0 me-1' + (showWindow[0]==true?' active':'')" @click="toggleCam(0)">📷🠟</button>
    <button :class="'btn btn-sm btn-outline-secondary p-0 ps-1 pe-1 m-0 me-1' + (showWindow[1]==true?' active':'')" @click="toggleCam(1)">📷🠝</button>
    <button :class="'btn btn-sm btn-outline-secondary p-0 ps-1 pe-1 m-0 me-1' + (showWindow[4]==true?' active':'')" @click="toggleMoviePanel()">&nbsp;✥&nbsp;</button>
  </div>

  <div class="row border bg-light machine-pos">
    <div class="col-3 p-1">
      X: {{ machinePos.x }}
    </div>
    <div class="col-3 p-1">
      Y: {{ machinePos.y }}
    </div>
    <div class="col-3 p-1">
      Z: {{ machinePos.z }}
    </div>
    <div class="col-3 p-1">
      A: {{ machinePos.a }}
    </div>
  </div>

  <Loading :loading="loading" />

  <DialogWrapper />

  <window :title="'Cam '+ settings.cams[0].name" :width="settings.cams[0].size.width + 28" :height="settings.cams[0].size.height + 100" :number="1" v-show="showWindow[0]" @close="closeCam(0)">
    <img v-if="showWindow[0]" ref="cam_feed0" :id="0" :src="videoSrc[0]" @click="moveOnClick">
    <canvas 
      v-if="showWindow[0]"
      ref="camCanvas0"
      :id="0"
      :width="settings.cams[0].size.width"
      :height="settings.cams[0].size.height" 
      :style="'position: relative; top: -' + settings.cams[0].size.height + 'px; margin-bottom: -' + (settings.cams[0].size.height - 12) + 'px;'"
      @click="moveOnClick">
    </canvas>
    <div class="form-check form-switch">
      <input @change="toggleLight(0)" :checked="lightsState[0]" class="form-check-input" type="checkbox" role="switch" id="topLight">
      <label class="form-check-label" for="topLight">Light</label>
    </div>
  </window>

  <window :title="'Cam '+ settings.cams[1].name" :width="settings.cams[1].size.width + 20" :height="settings.cams[1].size.height + 82" :number="2" v-show="showWindow[1]" @close="closeCam(1)">
    <img v-if="showWindow[1]" ref="cam_feed1" :id="1" :src="videoSrc[1]" @click="moveOnClick">
    <div class="form-check form-switch">
      <input @change="toggleLight(1)" :checked="lightsState[1]" class="form-check-input" type="checkbox" role="switch" id="bottomLight">
      <label class="form-check-label" for="bottomLight">Light</label>
    </div>
  </window>

  <window title="CV Top" :width="settings.cams[0].size.width + 20" :height="settings.cams[0].size.height + 82" :number="3" v-show="showWindow[2]" @close="closeCV(0)">
    <img ref="cv0" :src="CVResult[0].img" @click="getCV(0)" title="Click to Refresh">
    <div class="row m-0">
      <div class="col form-check form-switch">
        <input @change="toggleLight(0)" :checked="lightsState[0]" class="form-check-input" type="checkbox" role="switch" id="topLight">
        <label class="form-check-label" for="topLight">Light</label>
      </div>
      <div class="col form-check form-switch">
        <input v-model="CVLikeMachineView" @change="getCV(0)" class="form-check-input" type="checkbox" role="switch" id="machineView">
        <label class="form-check-label" for="machineView">Machine vision</label>
      </div>
    </div>
  </window>

  <window title="CV Bottom" :width="settings.cams[0].size.width + 20" :height="settings.cams[0].size.height + 82" :number="4" v-show="showWindow[3]" @close="closeCV(1)">
    <img ref="cv1" :src="CVResult[1].img" @click="getCV(1)" title="Click to Refresh">
    <div class="row m-0">
      <div class="col form-check form-switch">
        <input @change="toggleLight(1)" :checked="lightsState[1]" class="form-check-input" type="checkbox" role="switch" id="bottomLight">
        <label class="form-check-label" for="bottomLight">Light</label>
      </div>
      <div class="col form-check form-switch">
        <input v-model="CVLikeMachineView" @change="getCV(1)" class="form-check-input" type="checkbox" role="switch" id="machineView">
        <label class="form-check-label" for="machineView">Machine vision</label>
      </div>
    </div>
  </window>

  <window title="Move panel" :width="350" :height="680" :number="5" v-show="showWindow[4]" @close="closeMoviePanel()">
    <ControllerMovingNew
       @command="controllerMove($event)"
       @toggleValve="controllerToggleValve($event)"
       @togglePump="controllerTogglePump()"
       @toggleCamNozzlePosition="controllerToggleCamNozzlePosition()"

       :settings="settings"
       :movingOptions="movingOptions"
       :valvesState="valvesState"
       :pumpState="pumpState"
       :disabled="!controlsEnabled"
       :enabledUnderAlaram="controlsEnabledUnderAlarm">
    </ControllerMovingNew>
  </window>

  <ul class="nav nav-tabs">
    <li class="nav-item">
      <a :class="'nav-link' + (tab==0?' active':'')" @click="tab=0">Manual control</a>
    </li>
    <li class="nav-item">
      <a :class="'nav-link' + (tab==1?' active':'')" @click="tab=1">Settings</a>
    </li>
    <li class="nav-item">
      <a :class="'nav-link' + (tab==2?' active':'')" @click="tab=2">Projects</a>
    </li>
  </ul>

  <!-- Manual control Tab -->
  <div v-show="tab==0" class="row mt-2">
    
    <!--Column Left START -->
    <div class="col-md-auto left-column">
      <ControllerState
       :state="machineState"
       :pnpProcessing="pnpProcessing"
       :valvesState="valvesState"
       :pumpState="pumpState">
      </ControllerState>

      <ControllerMovingNew
       @command="controllerMove($event)"
       @toggleValve="controllerToggleValve($event)"
       @togglePump="controllerTogglePump()"
       @toggleCamNozzlePosition="controllerToggleCamNozzlePosition()"

       :settings="settings"
       :movingOptions="movingOptions"
       :valvesState="valvesState"
       :pumpState="pumpState"
       :disabled="!controlsEnabled"
       :enabledUnderAlaram="controlsEnabledUnderAlarm">
      </ControllerMovingNew>


    </div>
    <!--Column Left END -->
    
    <!--Column Central START -->
    <div class="col-md central-column">
      <div class="row">
        <div class="col">
          <ControllerGCode :disabled="!controlsEnabled" :machineState="machineState" :gCodeProcess="gCodeProcess" @run="gCodeRun($event)" @stop="gCodeStop()" @pause="gCodePause()"></ControllerGCode>
        </div>
      </div>

      <div class="row">
        <div class="col">
          <ControllerConsole :consoleLog="consoleLog" :disabled="!controlsEnabledUnderAlarm" @sendCommand="sendCommandUI([$event])"></ControllerConsole>
        </div>
      </div>

    </div>
    <!--Column Central END -->

    <!--Column Right START -->
    <div class="col-auto">
      <Vializer3D
           :width="600"
           :height="300"
           :x="machineState.pos.x"
           :y="machineState.pos.y"
           :z="machineState.pos.z"
           :a="machineState.pos.a"

           :x_max="0"
           :x_min="-200"
           :y_max="0"
           :y_min="-200"
           :z_max="55"
           :z_min="-55">
          </Vializer3D>
    </div>
    <!--Column Right END -->

  </div>


  <!-- Settings Tab -->
  <div v-show="tab==1" class="row mt-2">
    <div class="col">

      <div class="row flex-nowrap">
          <div class="col-auto">
              <div class="d-flex flex-column">
                  <ul class="nav nav-pills flex-column">
                      <li class="nav-item">
                        <a :class="'nav-link' + (tabSettings==0?' active':'')" @click="tabSettings=0">Controller</a>
                      </li>
                      <li class="nav-item">
                        <a :class="'nav-link' + (tabSettings==1?' active':'')" @click="tabSettings=1">Cameras</a>
                      </li>
                      <li class="nav-item">
                        <a :class="'nav-link' + (tabSettings==2?' active':'')" @click="tabSettings=2">Computer Vision</a>
                      </li>
                      <li class="nav-item">
                        <a :class="'nav-link' + (tabSettings==3?' active':'')" @click="tabSettings=3">Nozzles</a>
                      </li>
                      <li class="nav-item">
                        <a :class="'nav-link' + (tabSettings==4?' active':'')" @click="tabSettings=4">Nozzles Holder</a>
                      </li>
                      <li class="nav-item">
                        <a :class="'nav-link' + (tabSettings==5?' active':'')" @click="tabSettings=5">Heads</a>
                      </li>
                      <li class="nav-item">
                        <a :class="'nav-link' + (tabSettings==6?' active':'')" @click="tabSettings=6">Pump</a>
                      </li>
                      <li class="nav-item">
                        <a :class="'nav-link' + (tabSettings==7?' active':'')" @click="tabSettings=7">Parking</a>
                      </li>
                      <li class="nav-item">
                        <a :class="'nav-link' + (tabSettings==8?' active':'')" @click="tabSettings=8">Basket</a>
                      </li>
                      <li class="nav-item">
                        <a :class="'nav-link' + (tabSettings==9?' active':'')" @click="tabSettings=9">Feeders</a>
                      </li>
                      <li class="nav-item">
                        <a :class="'nav-link' + (tabSettings==10?' active':'')" @click="tabSettings=10">PCB Table</a>
                      </li>
                  </ul>
              </div>
          </div>
          <div class="col settings">
            <ControllerSettings
              v-if="tabSettings==0"
              :settings="machineState.settings"
              :disabled="!controlsEnabled"
              @sendCommand="sendCommands($event)">
            </ControllerSettings>

            <CamerasSettings 
              v-if="tabSettings==1"
              :cams="settings.cams"
              :machineState="machineState"
              :machinePos="machinePos"
              :settings="settings"
              :showWindow="showWindow"
              :disabled="!controlsEnabled"
              :loading="loading"
              @calibrate="calibrate($event)"
              @sendCommands="sendCommands($event, true)"
              @applaySettings="applaySettings()"
              @toggleCam="toggleCamParam($event)"
              @changeCamParam="changeCamParam($event)"
              @toggleMoviePanel="toggleMoviePanel()">
            </CamerasSettings>

            <CVSettings 
              v-if="tabSettings==2"
              :cvSettings="settings.cv"
              :showWindow="showWindow"
              :loading="loading"
              @toggleCV="toggleCV($event)"
              @applaySettings="applaySettings()">
            </CVSettings>

            <NozzlesSettings
              v-if="tabSettings==3"
              :nozzles="settings.nozzles"
              :machineState="machineState"
              :machinePos="machinePos"
              :settings="settings"
              :disabled="!controlsEnabled"
              :loading="loading"
              @autocalibrate="pnpAutocalibrateNozzle($event)"
              @applaySettings="applaySettings()">
            </NozzlesSettings>

            <NozzlesHolderSettings
              v-if="tabSettings==4"
              :nozzlesHolder="settings.nozzlesHolder"
              :machineState="machineState"
              :machinePos="machinePos"
              :settings="settings"
              :disabled="!controlsEnabled"
              :loading="loading"
              @putOnNozzle="pnpPutOnNozzle($event)"
              @applaySettings="applaySettings()">
            </NozzlesHolderSettings>

            <HeadsSettings
              v-if="tabSettings==5"
              :heads="settings.heads"
              :nozzles="settings.nozzles"
              :loading="loading"
              @applaySettings="applaySettings()">
            </HeadsSettings>

            <PumpSettings
              v-if="tabSettings==6"
              :pump="settings.pump"
              :loading="loading"
              @applaySettings="applaySettings()">
            </PumpSettings>

            <ParkingSettings
              v-if="tabSettings==7"
              :parking="settings.parking"
              :machineState="machineState"
              :machinePos="machinePos"
              :loading="loading"
              @applaySettings="applaySettings()">
            </ParkingSettings>

            <BasketSettings
              v-if="tabSettings==8"
              :basket="settings.basket"
              :machineState="machineState"
              :machinePos="machinePos"
              :loading="loading"
              @applaySettings="applaySettings()">
            </BasketSettings>

            <FeedersSettings
              v-if="tabSettings==9"
              :settings="settings"
              :cases="cases"
              :machineState="machineState"
              :machinePos="machinePos"
              :feeders="feeders"
              :disabled="!controlsEnabled"
              :loading="loading"
              @adjFeederPositionCV="pnpAdjFeederPositionCV($event)"
              @goToFeeder="pnpGoToFeeder($event)"
              @goToFeederCam="pnpGoToFeederCam($event)"
              @pickFromFeeder="pnpPickFromFeeder($event)"
              @adjPosition="pnpAdjPosition($event)"
              @dropIntoBasket="pnpDropIntoBasket($event)"
              @saveFeeders="saveJSON('', 'feeders', this.feeders)">
            </FeedersSettings>

            <PCBTableSettings
              v-if="tabSettings==10"
              :pcbtable="settings.table.pos"
              :machineState="machineState"
              :machinePos="machinePos"
              :loading="loading"
              @applaySettings="applaySettings()">
            </PCBTableSettings>

          </div>
      </div>

    </div>
  </div>


  <div v-show="tab==2" class="row mt-2">
    <div class="col">
      <Projects
        :project="project"
        :projects_list="projects_list"
        :disabled="!controlsEnabled"
        :loading="loading"
        :settings="settings"
        :cases="cases"
        :default_feeders="feeders"
        :machineState="machineState"
        :machinePos="machinePos"
        :pnpProcessing="pnpProcessing"
        
        @setSMDCase="setSMDCase($event)"

        @adjFeederPositionCV="pnpAdjFeederPositionCV($event)"
        @adjFeedersPositionCV="pnpAdjFeedersPositionCV($event)"
        @adjPCBPositionCV="pnpAdjPCBPositionCV($event)"
        @goToFeeder="pnpGoToFeeder($event)"
        @goToFeederCam="pnpGoToFeederCam($event)"
        @pickFromFeeder="pnpPickFromFeeder($event)"
        @adjPosition="pnpAdjPosition($event)"
        @dropIntoBasket="pnpDropIntoBasket($event)"

        @goToElement="pnpGoToElement($event)"
        @goToElementCam="pnpGoToElementCam($event)"
        @placeElement="pnpPlaceElement($event)"

        @setFeeders="setFeedersFromProject()"

        @newProject="newProject()"
        @loadProject="loadProject()"
        @saveProject="saveProject()"
        @renameProject="renameProject($event)"
        @deleteProject="deleteProject($event)"
        @run="pnpJobStart()"
        @runFrom="pnpJobStart($event)"
        @pause="pnpProcessingPause()"
        @stop="pnpProcessingStop()"
        >
      </Projects>
    </div>
  </div>


<hr>

</div>
</template>

<style>

.container {
  max-width: 100%;
}

@media (min-width: 768px) {
.left-column {
      width: 400px;
  }
}

.central-column {
  min-width: 20%;
}

.btn-outline-secondary {
    color: #606970;
    border-color: #6c757d;
    background-color: #f1f1f1;
}

.btn-outline-secondary:disabled, .btn-outline-secondary.disabled {
    color: #6c757d;
    background-color: #f1f1f1;
}

.form-control {
  -webkit-appearance: auto;
  appearance: auto;
}

input[type=range] {
  -webkit-appearance: none;
  margin: 18px 0;
  width: 100%;
}
input[type=range]:focus {
  outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
  width: 100%;
  height: 4.4px;
  cursor: pointer;
  /*box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;*/
  background: #ced4da;
  border-radius: 3.3px;
  border: 0.2px solid  #ced4da;
}
input[type=range]::-webkit-slider-thumb {
  /*box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;*/
  border: 1px solid #000000;
  height: 36px;
  width: 16px;
  border-radius: 3px;
  background: #ffffff;
  cursor: pointer;
  -webkit-appearance: none;
  margin-top: -14px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
  background: #367ebd;
}
input[type=range]::-moz-range-track {
  width: 100%;
  height: 4.4px;
  cursor: pointer;
  /*box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;*/
  background: #ced4da;
  border-radius: 3.3px;
  border: 0.2px solid #ced4da;
}
input[type=range]::-moz-range-thumb {
  /*box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;*/
  border: 1px solid #ced4da;
  height: 36px;
  width: 16px;
  border-radius: 3px;
  background: #f1f1f1;
  cursor: pointer;
}
input[type=range]::-ms-track {
  width: 100%;
  height: 6.4px;
  cursor: pointer;
  background: transparent;
  border-color: transparent;
  border-width: 16px 0;
  color: transparent;
}
input[type=range]::-ms-fill-lower {
  background: #2a6495;
  border: 0.2px solid  #8a8a8a;
  border-radius: 2.6px;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}
input[type=range]::-ms-fill-upper {
  background: #3071a9;
  border: 0.2px solid  #8a8a8a;
  border-radius: 2.6px;
  /*box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;*/
}
input[type=range]::-ms-thumb {
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
  border: 1px solid #000000;
  height: 36px;
  width: 16px;
  border-radius: 3px;
  background: #ffffff;
  cursor: pointer;
}
input[type=range]:focus::-ms-fill-lower {
  background: #3071a9;
}
input[type=range]:focus::-ms-fill-upper {
  background: #367ebd;
}
a:not([href]) {
  cursor:pointer;
}

#container3D {
  width: 600px;
  height: 400px;
  border: 1px solid;
}

.machine-pos {
  margin-left: 2px;
  width: 26em;
  position: fixed;
  top: 2px;
  z-index: 1000;
}

.tool-buttons {
  margin-left: 28em;
  width: auto;
  position: fixed;
  top: 2px;
  z-index: 1000;
}

</style>