<template>
  <div>
    <v-container
      class="pa-3"
      fluid
    >
      <v-row
        no-gutters
        align="center"
        justify="center"
      >
        <v-col
          cols="12"
          :class="['pb-3 ', 'pr-lg-3']"
          lg="8"
          align-self="stretch"
        >
          <v-card
            color="primary"
            height="100%"
            style="display: flex; flex-direction: column"
            dark
          >
            <v-card-title
              class="pb-0 mb-0 pl-4 pt-1"
              style="height: 15%; min-height: 50px;"
            >
              Cameras
              <v-switch
                v-model="driverMode"
                label="Driver Mode"
                style="margin-left: auto;"
                color="accent"
              />
            </v-card-title>
            <v-row
              align="center"
            >
              <v-col
                v-for="idx in (selectedOutputs instanceof Array ? selectedOutputs : [selectedOutputs])"
                :key="idx"
                cols="12"
                :md="selectedOutputs.length === 1 ? 12 : Math.floor(12 / selectedOutputs.length)"
                class="pb-0 pt-0"
                style="height: 100%;"
              >
                <div style="position: relative; width: 100%; height: 100%;">
                  <cvImage
                    :id="idx === 0 ? 'normal-stream' : ''"
                    :address="$store.getters.streamAddress[idx]"
                    :disconnected="!$store.state.backendConnected"
                    scale="100"
                    :max-height="$store.getters.isDriverMode ? '40vh' : '300px'"
                    :max-height-md="$store.getters.isDriverMode ? '50vh' : '320px'"
                    :max-height-xl="$store.getters.isDriverMode ? '60vh' : '450px'"
                    :alt="'Stream' + idx"
                    :color-picking="$store.state.colorPicking && idx == 0"
                    @click="onImageClick"
                  />
                </div>
              </v-col>
            </v-row>
          </v-card>
        </v-col>
        <v-col
          cols="12"
          class="pb-3"
          lg="4"
          align-self="stretch"
        >
          <v-card
            color="primary"
          >
            <camera-and-pipeline-select />
          </v-card>
          <v-card
            :disabled="$store.getters.isDriverMode || $store.state.colorPicking"
            class="mt-3"
            color="primary"
          >
            <v-row
              align="center"
              class="pl-3 pr-3"
            >
              <!--  -->
              <v-col lg="12">
                <p style="color: white;">
                  Processing mode:
                </p>
                <v-btn-toggle
                  v-model="processingMode"
                  mandatory
                  dark
                  class="fill"
                >
                  <v-btn
                    color="secondary"
                  >
                    <v-icon>mdi-crop-square</v-icon>
                    <span>2D</span>
                  </v-btn>
                  <v-btn
                    color="secondary"
                    @click="on3DClick"
                  >
                    <v-icon>mdi-cube-outline</v-icon>
                    <span>3D</span>
                  </v-btn>
                </v-btn-toggle>
              </v-col>
              <v-col lg="12">
                <p style="color: white;">
                  Stream display:
                </p>
                <v-btn-toggle
                  v-model="selectedOutputs"
                  :multiple="$vuetify.breakpoint.mdAndUp"
                  mandatory
                  dark
                  class="fill"
                >
                  <v-btn
                    color="secondary"
                    class="fill"
                  >
                    <v-icon>mdi-palette</v-icon>
                    <span>Normal</span>
                  </v-btn>
                  <v-btn
                    color="secondary"
                    class="fill"
                  >
                    <v-icon>mdi-compare</v-icon>
                    <span>Threshold</span>
                  </v-btn>
                </v-btn-toggle>
              </v-col>
            </v-row>
          </v-card>
        </v-col>
      </v-row>
      <v-row no-gutters>
        <v-col
          v-for="(tabs, idx) in tabGroups"
          :key="idx"
          :cols="Math.floor(12 / tabGroups.length)"
          :class="idx != tabGroups.length - 1 ? 'pr-3' : ''"
          align-self="stretch"
        >
          <v-card
            color="primary"
            height="100%"
            class="pr-4 pl-4"
          >
            <v-tabs
              v-if="!$store.getters.isDriverMode"
              v-model="selectedTabs[idx]"
              grow
              background-color="primary"
              dark
              height="48"
              slider-color="accent"
            >
              <v-tab
                v-for="(tab, i) in tabs.filter(it => it.name !== '3D' || $store.getters.currentPipelineSettings.solvePNPEnabled)"
                :key="i"
              >
                {{ tab.name }}
              </v-tab>
            </v-tabs>
            <div class="pl-4 pr-4 pt-2">
              <keep-alive>
                <component
                  :is="(tabs[selectedTabs[idx]] || tabs[0]).component"
                  :ref="(tabs[selectedTabs[idx]] || tabs[0]).name"
                  v-model="$store.getters.pipeline"
                  @update="$emit('save')"
                />
              </keep-alive>
            </div>
          </v-card>
        </v-col>
      </v-row>
    </v-container>
    <!-- snack bar and modal -->
    <v-snackbar
      v-model="snackbar"
      :timeout="3000"
      top
      color="error"
    >
      <span style="color:#000">Can not remove the only pipeline!</span>
      <v-btn
        color="black"
        text
        @click="snackbar = false"
      >
        Close
      </v-btn>
    </v-snackbar>

    <v-dialog
      v-model="dialog"
      width="500"
    >
      <v-card
        color="primary"
        dark
      >
        <v-card-title>
          Current resolution not calibrated
        </v-card-title>

        <v-card-text>
          Because the current resolution {{ this.$store.getters.videoFormatList[this.$store.getters.currentPipelineSettings.cameraVideoModeIndex].width }}
          x {{ this.$store.getters.videoFormatList[this.$store.getters.currentPipelineSettings.cameraVideoModeIndex].height }}
          is not yet calibrated, 3D mode cannot be enabled. Please
          <a
            href="/#/cameras"
            class="white--text"
            @click="$emit('switch-to-cameras')"
          > visit the Cameras tab</a> to calibrate this resolution. For now, SolvePNP will do nothing.
        </v-card-text>

        <v-divider />

        <v-card-actions>
          <v-spacer />
          <v-btn
            color="white"
            text
            @click="closeUncalibratedDialog"
          >
            OK
          </v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
  </div>
</template>

<script>
    import CameraAndPipelineSelect from "../components/pipeline/CameraAndPipelineSelect";
    import cvImage from '../components/common/cv-image';
    import InputTab from './PipelineViews/InputTab';
    import ThresholdTab from './PipelineViews/ThresholdTab';
    import ContoursTab from './PipelineViews/ContoursTab';
    import OutputTab from './PipelineViews/OutputTab';
    import TargetsTab from "./PipelineViews/TargetsTab";
    import PnPTab from './PipelineViews/PnPTab';

    export default {
        name: 'CameraTab',
        components: {
            CameraAndPipelineSelect,
            cvImage,
            InputTab,
            ThresholdTab,
            ContoursTab,
            OutputTab,
            TargetsTab,
            PnPTab,
        },
        data() {
            return {
                selectedTabsData: [0, 0, 0, 0],
                snackbar: false,
                counterData: 0,
                dialog: false,
                processingModeOverride: false
            }
        },
        computed: {
            selectedTabs: {
                get() {
                  return this.$store.getters.isDriverMode ? [0] : this.selectedTabsData;
                },
                set(value) {
                  this.selectedTabsData = value;
                }
            },
            tabGroups: {
                get() {
                    let tabs = {
                        input: {
                            name: "Input",
                            component: "InputTab",
                        },
                        threshold: {
                            name: "Threshold",
                            component: "ThresholdTab",
                        },
                        contours: {
                            name: "Contours",
                            component: "ContoursTab",
                        },
                        output: {
                            name: "Output",
                            component: "OutputTab",
                        },
                        targets: {
                            name: "Target Info",
                            component: "TargetsTab",
                        },
                        pnp: {
                            name: "3D",
                            component: "PnPTab",
                        }
                    };

                    // 2D array of tab names and component names; each sub-array is a separate tab group
                    let ret = [];
                    if (this.$vuetify.breakpoint.smAndDown || this.$store.getters.isDriverMode || (this.$vuetify.breakpoint.mdAndDown && !this.$store.state.compactMode)) {
                        // One big tab group with all the tabs
                        ret[0] = Object.values(tabs);
                    } else if (this.$vuetify.breakpoint.mdAndDown || !this.$store.state.compactMode) {
                        // Two tab groups, one with "input, threshold, contours, output" and the other with "target info, 3D"
                        ret[0] = [tabs.input, tabs.threshold, tabs.contours, tabs.output];
                        ret[1] = [tabs.targets, tabs.pnp];
                    } else if (this.$vuetify.breakpoint.lgAndDown) {
                        // Three tab groups, one with "input", one with "threshold, contours, output", and the other with "target info, 3D"
                        ret[0] = [tabs.input];
                        ret[1] = [tabs.threshold, tabs.contours, tabs.output];
                        ret[2] = [tabs.targets, tabs.pnp];
                    } else if (this.$vuetify.breakpoint.xl) {
                        // Three tab groups, one with "input", one with "threshold, contours", and the other with "output, target info, 3D"
                        ret[0] = [tabs.input];
                        ret[1] = [tabs.threshold];
                        ret[2] = [tabs.contours, tabs.output]
                        ret[3] = [tabs.targets, tabs.pnp];
                    }

                    return ret;
                }
            },
            processingMode: {
                get() {
                    return (this.$store.getters.currentPipelineSettings.solvePNPEnabled || this.processingModeOverride) ? 1 : 0;
                },
                set(value) {
                    if (this.$store.getters.isCalibrated) {
                      this.$store.getters.currentPipelineSettings.solvePNPEnabled = value === 1;
                      this.handlePipelineUpdate("solvePNPEnabled", value === 1);
                    }
                }
            },
            driverMode: {
                get() {
                  return this.$store.getters.isDriverMode;
                },
                set(value) {
                  this.$store.getters.currentCameraSettings.currentPipelineIndex = value ? -1 : 0;
                  this.handleInputWithIndex('currentPipeline', value ? -1 : 0);
                }
            },
            selectedOutputs: {
                // All this logic exists to deal with the reality that the output select buttons sometimes need an array and sometimes need a number (depending on whether or not they're exclusive)
                get() {
                    // We switch the selector to single-select only on sm-and-down size devices, so we have to return a Number instead of an Array in that state
                    let ret;
                    if (this.$store.state.colorPicking) {
                        ret = [0]; // We want the input stream only while color picking
                    } else if (!this.$store.getters.isDriverMode) {
                        ret = this.$store.state.selectedOutputs || [0];
                    } else {
                        ret = [1]; // We want the output stream in driver mode
                    }

                    if (this.$vuetify.breakpoint.mdAndUp) {
                        return ret;
                    } else {
                        return ret[0] || 0;
                    }
                },
                set(value) {
                    let valToCommit = [0];
                    if (value instanceof Array) {
                        // Value is already an array, we don't need to do anything
                        value.sort(); // Sort for visual consistency
                        valToCommit = value;
                    } else if (value) {
                        // Value is assumed to be a number, so we wrap it into an array
                        valToCommit = [value];
                    }
                    this.$store.commit("selectedOutputs", valToCommit);
                    // TODO: Currently the backend just sends both streams regardless of the selected outputs value, so we don't need to send anything
                    // this.handlePipelineUpdate('selectedOutputs', valToCommit);
                }
            },
            latency: {
                get() {
                    return this.$store.getters.currentPipelineResults.latency;
                }
            }
        },
        methods: {
            isCalibrated() {
                const resolution = this.$store.getters.videoFormatList[this.$store.getters.currentPipelineSettings.cameraVideoModeIndex];
                return this.$store.getters.currentCameraSettings.calibrations
                    .some(e => e.width === resolution.width && e.height === resolution.height)
            },
            onImageClick(event) {
                // Only run on the input stream
                if (event.target.alt !== "Stream0") return;
                // Get a reference to the threshold tab (if it is shown) and call its "onClick" method
                let ref = this.$refs["Threshold"];
                if (ref && ref[0])
                  ref[0].onClick(event)
            },
            on3DClick() {
                if (!this.$store.getters.isCalibrated) {
                  this.dialog = true;
                  this.processingModeOverride = true;
                }
            },
            closeUncalibratedDialog() {
                this.dialog = false;
                this.processingModeOverride = false;
                // this.$store.getters.currentPipelineSettings.solvePNPEnabled = false;
                this.handlePipelineUpdate("solvePNPEnabled", false);
            }
        }
    }
</script>

<style scoped>
    .v-btn-toggle.fill {
        width: 100%;
        height: 100%;
    }

    .v-btn-toggle.fill > .v-btn {
        width: 50%;
        height: 100%;
    }

    th {
        width: 80px;
        text-align: center;
    }
</style>