<template>
  <div>
    <vc-date-picker v-if="lazyValue.type === 'date'" mode="date" v-model="dateValue" :is-range="lazyValue.combobox"></vc-date-picker>
    <vc-date-picker v-else-if="lazyValue.type === 'time'" mode="time" v-model="dateValue"
      class="hide-header" :is-range="lazyValue.combobox"></vc-date-picker>
    <vc-date-picker v-else-if="lazyValue.type === 'datetime'" mode="datetime" v-model="dateValue" :is-range="lazyValue.combobox"></vc-date-picker>
    <v-checkbox v-else-if="lazyValue.type === 'boolean'" dense :readonly="lazyValue.readonly" v-model="booleanValue"
      :label="lazyValue.title" :hint="lazyValue.description" :placeholder="lazyValue.placeholder" persistent-hint
      @change="save" :class="lazyValue.description ? 'mb-2' : ''"></v-checkbox>
    <div v-else-if="lazyValue.type === 'qrcode'">
      <div class="subtitle-2"> {{ lazyValue.title }}</div>
      <v-img :src="qrcode"></v-img>
    </div>
    <div v-else-if="lazyValue.type === 'button'" @click="save">
      <v-btn small block> {{ lazyValue.title }} </v-btn>
      <span v-if="lazyValue.description" class="caption pl-1">{{
        lazyValue.description
      }}</span>
    </div>
    <v-combobox v-else-if="lazyValue.choices && lazyValue.combobox" dense :readonly="lazyValue.readonly"
      :items="lazyValue.choices" :multiple="lazyValue.multiple" :small-chips="lazyValue.multiple"
      v-model="lazyValue.value" outlined :label="lazyValue.title" :hint="lazyValue.description" persistent-hint
      :placeholder="lazyValue.placeholder">
      <template v-slot:append-outer>
        <v-btn v-if="dirty && device" color="success" @click="save" class="shift-up">
          <v-icon>send</v-icon>
        </v-btn>
      </template>
    </v-combobox>
    <v-select v-else-if="lazyValue.choices" dense :readonly="lazyValue.readonly" :items="lazyValue.choices"
      :multiple="lazyValue.multiple" :small-chips="lazyValue.multiple" v-model="lazyValue.value" outlined
      :label="lazyValue.title" :hint="lazyValue.description" persistent-hint :placeholder="lazyValue.placeholder">
      <template v-slot:append-outer>
        <v-btn v-if="dirty && device" color="success" @click="save" class="shift-up">
          <v-icon>send</v-icon>
        </v-btn>
      </template>
    </v-select>
    <DevicePicker v-else-if="lazyValue.type === 'device'" v-model="lazyValue.value" :multiple="lazyValue.multiple"
      :readonly="lazyValue.readonly" :devices="devices" :title="lazyValue.title" :description="lazyValue.description">
      <template v-slot:append-outer>
        <v-btn v-if="dirty && device" color="success" @click="save" class="shift-up">
          <v-icon>send</v-icon>
        </v-btn>
      </template>
    </DevicePicker>
    <DevicePicker v-else-if="lazyValue.type === 'interface'" v-model="lazyValue.value" :multiple="lazyValue.multiple"
      :readonly="lazyValue.readonly" :devices="interfaces" :title="lazyValue.title" :description="lazyValue.description">
      <template v-slot:append-outer>
        <v-btn v-if="dirty && device" color="success" @click="save" class="shift-up">
          <v-icon>send</v-icon>
        </v-btn>
      </template>
    </DevicePicker>
    <div v-else-if="lazyValue.type === 'clippath'" class="mb-2">
      <v-btn small block @click="editZone">{{ lazyValue.title }} </v-btn>
      <Camera :value="device" :device="device" :clipPathValue="sanitizedClipPathValue" :showDialog="editingZone"
        :hidePreview="true" @dialog="editingZoneChanged" @clipPath="updateClipPath"></Camera>
    </div>
    <v-textarea v-else-if="lazyValue.type === 'textarea'" v-model="lazyValue.value" outlined persistent-hint
      :hint="lazyValue.description" :label="lazyValue.title">

    </v-textarea>
    <v-text-field v-else autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" dense
      :readonly="lazyValue.readonly" outlined v-model="lazyValue.value" :placeholder="lazyValue.placeholder"
      :label="lazyValue.title" :hint="lazyValue.description" persistent-hint
      :type="lazyValue.type === 'password' ? 'password' : undefined">
      <template v-slot:append-outer>
        <v-btn v-if="dirty && device" color="success" text @click="save" class="shift-up">
          <v-icon>send</v-icon>
        </v-btn>
      </template>
    </v-text-field>
  </div>
</template>
<script>
import RPCInterface from "./RPCInterface.vue";
import DevicePicker from "../common/DevicePicker.vue";
import Grower from "../common/Grower.vue";
import cloneDeep from "lodash/cloneDeep";
import Camera from "./Camera.vue";
import qrcode from "qrcode";

export default {
  mixins: [RPCInterface],
  components: {
    Camera,
    DevicePicker,
    Grower,
  },
  data() {
    return {
      editingZone: false,
      clipPathThrottle: null,
    };
  },
  watch: {
    dirty() {
      if (this.device) return;
      this.onInput();
    },
  },
  asyncComputed: {
    qrcode: {
      async get() {
        if (this.lazyValue.type !== "qrcode") return;

        let color;
        if (this.$vuetify.theme.dark) {
          color = {
            dark: "#FFFFFFFF",
            light: "#FF000000",
          };
        } else {
          color = {
            light: "#FFFFFFFF",
            dark: "#404040FF",
          };
        }

        return qrcode.toDataURL(this.lazyValue.value, {
          margin: 0.5,
          color,
          width: 320,
          rendererOpts: {
            type: "image/jpeg",
          },
        });
      },
      default: "https://poops.com/farts.jpg",
    },
  },
  computed: {
    sanitizedClipPathValue() {
      try {
        return JSON.parse(JSON.stringify(this.lazyValue.value)) || [];
      } catch (e) {
        return [];
      }
    },
    dateValue: {
      get() {
        if (this.lazyValue.combobox) {
          return {
            start: new Date(parseInt(this.lazyValue.value?.[0]) || Date.now()),
            end: new Date(parseInt(this.lazyValue.value?.[1]) || Date.now()),
          };
        }
        return new Date(parseInt(this.lazyValue.value) || Date.now());
      },
      set(val) {
        if (this.lazyValue.combobox) {
          this.lazyValue.value = [val.start.getTime(), val.end.getTime()];
        }
        else {
          this.lazyValue.value = val.getTime();
        }
      }
    },
    booleanValue: {
      get() {
        return (
          this.lazyValue.value &&
          this.lazyValue.value.toString().toLowerCase() === "true"
        );
      },
      set(val) {
        this.lazyValue.value = !!val;
      },
    },
    dirty() {
      return (
        JSON.stringify(this.lazyValue.value) !==
        JSON.stringify(this.value.value)
      );
    },
    devices() {
      var expression;
      try {
        expression = this.lazyValue.deviceFilter || "true;";
        // var interfaces = this.$scrypted.systemManager.getDeviceById(id).interfaces.map(iface => `var ${iface} = true`);
      } catch (e) {
        expression = "true;";
      }
      var ret = this.$store.state.scrypted.devices
        .map((id) => this.$scrypted.systemManager.getDeviceById(id))
        .filter((device) => {
          try {
            return eval(
              `(function() { var interfaces = ${JSON.stringify(
                device.interfaces
              )}; var type='${device.type}'; var id = '${device.id}'; return ${expression} })`
            )();
          } catch (e) {
            return true;
          }
        })
        .map((device) => ({
          id: device.id,
          text: device.name,
        }));
      if (!this.lazyValue.multiple) {
        ret.splice(0, 0, {
          id: null,
          text: this.lazyValue.placeholder || "Select a Device",
        });
      }
      return ret;
    },
    interfaces() {
      var expression;
      try {
        expression = this.lazyValue.deviceFilter || "true;";
        // var interfaces = this.$scrypted.systemManager.getDeviceById(id).interfaces.map(iface => `var ${iface} = true`);
      } catch (e) {
        expression = "true;";
      }
      var ret = this.$store.state.scrypted.devices
        .map((id) => {
          const device = this.$scrypted.systemManager.getDeviceById(id);
          return device.interfaces.map((iface) => ({
            device,
            deviceInterface: iface,
          }));
        })
        .flat()
        .filter(({ device, deviceInterface }) => {
          try {
            return eval(
              `(function() { var interfaces = ${JSON.stringify(
                device.interfaces
              )}; var deviceInterface = '${deviceInterface}'}; var type='${device.type
              }'; return ${expression} })`
            )();
          } catch (e) {
            return true;
          }
        })
        .map(({ device, deviceInterface }) => ({
          id: device.id + "#" + deviceInterface,
          text: device.name + ` (${deviceInterface})`,
        }));
      if (!this.lazyValue.multiple) {
        ret.splice(0, 0, {
          id: null,
          text: this.lazyValue.placeholder || "Select an Interface",
        });
      }
      return ret;
    },
  },
  methods: {
    onChange() { },
    updateClipPath(e) {
      clearTimeout(this.clipPathThrottle);
      this.clipPathThrottle = setTimeout(() => {
        this.lazyValue.value = e;
        this.rpc().putSetting(
          this.lazyValue.key,
          this.createInputValue().value
        );
        this.onInput();
      }, 500)
    },
    editingZoneChanged(value) {
      this.editingZone = value;
      if (!value) {
        this.rpc().putSetting(
          this.lazyValue.key,
          this.createInputValue().value
        );
        this.onInput();
      }
    },
    createLazyValue() {
      var type = this.value.type || "";

      if (type.indexOf("[]") == -1 && type !== "clippath") {
        return cloneDeep(this.value);
      }

      var ret = cloneDeep(this.value);
      try {
        ret.value = JSON.parse(ret.value);
      } catch (e) {
        ret.value = [];
      }
      return ret;
    },
    createInputValue() {
      var type = this.lazyValue.type || "";

      if (type.indexOf("[]") == -1 && type !== "clippath") {
        return this.lazyValue;
      }

      var ret = cloneDeep(this.lazyValue);
      ret.value = JSON.stringify(ret.value.filter((id) => id));
      return ret;
    },
    save() {
      this.rpc().putSetting(this.lazyValue.key, this.createInputValue().value);
      this.onInput();
    },
    editZone() {
      this.editingZone = true;
    },
  },
};
</script>
<style scoped>
.shift-up {
  margin-top: -8px;
}

.hide-header .vc-date {
  display: none !important;
}
</style>
