<template>
  <div class="my-n8">
    <v-row v-if="formState.ready" dense>
      <gz-error :error-box-message="formState.errorBoxMessage"></gz-error>

      <v-col v-if="showSelector" cols="12">
        <v-dialog
          v-model="showSelector"
          scrollable
          max-width="600px"
          data-cy="dashSelector"
          @keydown.esc="cancel"
        >
          <v-card elevation="24">
            <v-card-title class="text-h5 lighten-2" primary-title>
              <span> {{ $sock.t("Add") }} </span>
            </v-card-title>

            <v-card-text style="height: 500px">
              <v-list>
                <v-list-item
                  v-for="item in availableItems()"
                  :key="item.id"
                  @click="addItem(item)"
                >
                  <v-list-item-icon
                    ><v-icon>{{ item.icon }}</v-icon></v-list-item-icon
                  >
                  <v-list-item-title>{{
                    $sock.t(item.title)
                  }}</v-list-item-title>
                </v-list-item>
              </v-list>
            </v-card-text>

            <v-divider></v-divider>
            <v-card-actions>
              <v-btn
                color="primary"
                text
                data-cy="dashSelector:cancel"
                @click.native="showSelector = false"
                >{{ $sock.t("Cancel") }}</v-btn
              >
            </v-card-actions>
          </v-card>
        </v-dialog>
      </v-col>
    </v-row>
    <v-row dense>
      <v-col
        v-for="item in effectiveView"
        :key="item.id"
        class="d-flex child-flex"
        cols="12"
        sm="6"
        lg="4"
      >
        <component
          :is="item.type"
          v-bind="item"
          :max-list-items="10"
          @dash-remove="dashRemove"
          @dash-move-start="dashMoveStart"
          @dash-move-back="dashMoveBack"
          @dash-move-forward="dashMoveForward"
          @dash-move-end="dashMoveEnd"
          @dash-change="dashSaveSettings"
        >
        </component>
      </v-col>
      <v-col cols="12">
        <v-btn
          v-if="formState.ready"
          text
          @click.native="showSelector = true"
          >{{ $sock.t("Add") }}</v-btn
        >
      </v-col>
    </v-row>
  </div>
</template>

<script>
const FORM_KEY = "home-dashboard";
import DashRegistry from "../api/dash-registry";
//---------- DASH ITEMS ----------
import GzDashTodayReminders from "../components/dash-today-reminders.vue";
import GzDashTodayReviews from "../components/dash-today-reviews.vue";
export default {
  components: {
    GzDashTodayReminders,
    GzDashTodayReviews
  },
  data() {
    return {
      effectiveView: [],
      showSelector: false,
      formState: {
        ready: false,
        dirty: false,
        valid: true,
        readOnly: false,
        loading: true,
        errorBoxMessage: null,
        appError: null,
        serverError: {}
      }
    };
  },
  beforeCreate() {
    window.$gz.eventBus.$emit("menu-change", {
      isMain: true,
      icon: "$sockiTachometer",
      title: "Dashboard",
      helpUrl: "home-dashboard"
    });
  },
  async created() {
    const vm = this;

    try {
      await DashRegistry.cacheTranslationsForAvailableItems();
      //users have full rights to their dashboard config
      vm.rights = window.$gz.role.fullRightsObject();
      vm.formState.readOnly = false;
      window.$gz.eventBus.$on("menu-click", clickHandler);

      await vm.getDataFromApi();
      window.$gz.form.setFormState({
        vm: vm,
        dirty: false,
        valid: true
      });
      generateMenu(vm);
    } catch (error) {
      window.$gz.errorHandler.handleFormError(error, vm);
    } finally {
      vm.formState.ready = true;
    }
  },
  methods: {
    dashSaveSettings: function() {
      this.saveView();
    },
    dashMoveStart: function(id) {
      this.move("start", id);
    },
    dashMoveBack: function(id) {
      this.move("left", id);
    },
    dashMoveForward: function(id) {
      this.move("right", id);
    },
    dashMoveEnd: function(id) {
      this.move("end", id);
    },
    dashRemove: function(id) {
      const index = this.getEffectiveViewItemIndexById(id);
      if (index == -1) {
        return;
      }
      this.effectiveView.splice(index, 1);
      this.saveView();
    },
    move: function(direction, id) {
      const index = this.getEffectiveViewItemIndexById(id);
      if (index == -1) {
        return;
      }

      const totalItems = this.effectiveView.length;
      let newIndex = 0;
      //calculate new index
      switch (direction) {
        case "start":
          newIndex = 0;
          break;
        case "left":
          newIndex = index - 1;
          if (newIndex < 0) {
            newIndex = 0;
          }
          break;
        case "right":
          newIndex = index + 1;
          if (newIndex > totalItems - 1) {
            newIndex = totalItems - 1;
          }
          break;
        case "end":
          newIndex = totalItems - 1;
          break;
      }

      this.effectiveView.splice(
        newIndex,
        0,
        this.effectiveView.splice(index, 1)[0]
      );
      this.saveView();
    },
    getEffectiveViewItemIndexById: function(id) {
      return this.effectiveView.findIndex(z => z.id == id);
    },
    addItem: function(item) {
      this.showSelector = false;
      const newItem = JSON.parse(JSON.stringify(item));
      newItem.id = Date.now();
      this.effectiveView.push(newItem);
      this.saveView();
    },
    availableItems: function() {
      const allItems = DashRegistry.availableItems();
      // console.log("availableItems:allItems", JSON.stringify(allItems));
      // console.log(
      //   "availableItems:effectiveView",
      //   JSON.stringify(this.effectiveView)
      // );
      const ret = [];
      allItems.forEach(z => {
        if (!z.singleOnly) {
          ret.push(z);
        } else {
          if (this.effectiveView.findIndex(m => m.type == z.type) == -1) {
            ret.push(z);
          }
        }
      });

      // console.log("availableItems:ret", JSON.stringify(ret));
      return ret;
    },
    async getDataFromApi() {
      const vm = this;
      window.$gz.form.setFormState({
        vm: vm,
        loading: true
      });

      try {
        window.$gz.form.deleteAllErrorBoxErrors(vm);
        const res = await window.$gz.api.get("dashboard-view");
        if (res.error) {
          if (res.error.code == "2010") {
            window.$gz.form.handleObjectNotFound(vm);
          }
          vm.formState.serverError = res.error;
          window.$gz.form.setErrorBoxErrors(vm);
        } else {
          const savedView = JSON.parse(res.data.view);
          const availableItems = DashRegistry.availableItems();
          //filter out any that are deprecated or no longer accessible due to role change
          const allowedView = savedView.filter(z =>
            availableItems.find(m => m.type == z.type)
          );
          vm.effectiveView = allowedView;
          generateMenu(vm);
          window.$gz.form.setFormState({
            vm: vm,
            dirty: false,
            valid: true,
            loading: false
          });
        }
      } catch (error) {
        window.$gz.errorHandler.handleFormError(error, vm);
      } finally {
        window.$gz.form.setFormState({
          vm: vm,
          loading: false
        });
      }
    },
    async saveView() {
      const vm = this;
      if (vm.canSave == false) {
        return;
      }
      try {
        window.$gz.form.setFormState({
          vm: vm,
          loading: true
        });
        window.$gz.form.deleteAllErrorBoxErrors(vm);
        const res = await window.$gz.api.put(
          "dashboard-view",
          JSON.stringify(vm.effectiveView)
        );

        if (res.error) {
          vm.formState.serverError = res.error;
          window.$gz.form.setErrorBoxErrors(vm);
        } else {
          window.$gz.form.setFormState({
            vm: vm,
            dirty: false,
            valid: true
          });
        }
      } catch (ex) {
        window.$gz.errorHandler.handleFormError(ex, vm);
      } finally {
        window.$gz.form.setFormState({
          vm: vm,
          loading: false
        });
      }
    }
  }
};

/////////////////////////////
//
//
async function clickHandler(menuItem) {
  if (!menuItem) {
    return;
  }
  const m = window.$gz.menu.parseMenuItem(menuItem);
  if (m.owner == FORM_KEY && !m.disabled) {
    switch (m.key) {
      case "add-dash":
        m.vm.showSelector = true;
        break;
      case "WorkOrderItemScheduledUserList":
        m.vm.$router
          .push({
            name: "svc-workorder-item-scheduled-users",
            params: {
              aType: window.$gz.type.User,
              objectId: m.vm.$store.state.userId,
              name: m.vm.$store.state.userName
            }
          })
          .catch(() => {});
        break;
      case "WorkOrderItemLaborList":
        m.vm.$router
          .push({
            name: "svc-workorder-item-labors",
            params: {
              aType: window.$gz.type.User,
              objectId: m.vm.$store.state.userId,
              name: m.vm.$store.state.userName
            }
          })
          .catch(() => {});
        break;
      default:
        window.$gz.eventBus.$emit(
          "notify-warning",
          FORM_KEY + "::context click: [" + m.key + "]"
        );
    }
  }
}

//////////////////////
//
//
function generateMenu(vm) {
  const menuOptions = {
    isMain: true,
    icon: "$sockiTachometer",
    title: "Dashboard",
    helpUrl: "home-dashboard",
    menuItems: []
  };

  menuOptions.menuItems.push({
    title: "Add",
    icon: "$sockiPlus",
    key: FORM_KEY + ":add-dash",
    vm: vm
  });
  menuOptions.menuItems.push({ divider: true, inset: false });

  window.$gz.eventBus.$emit("menu-change", menuOptions);
}
</script>
