<template>
  <v-app>
    <gznotify ref="gznotify"></gznotify>
    <gzconfirm ref="gzconfirm"></gzconfirm>
    <!-- Width of nav drawer set to allow widest translated text menu item to show which is spanish client service requests item 
    and also leave a tiny space to click on outside of nav for galaxy 9 phone (narrowest width supported device) 
    
    Also there is a height bug in vuetify with chrome on mobile (and safari) so using workaround with 100% height set on v-navigation-drawer
    https://github.com/vuetifyjs/vuetify/issues/9607
     
    -->

    <v-navigation-drawer
      v-if="isAuthenticated"
      v-model="drawer"
      app
      temporary
      width="345"
      height="100%"
    >
      <template v-slot:prepend>
        <div class="subtitle-2 primary--text pt-2 pl-4">
          {{ $store.state.userName }}
        </div>
      </template>

      <v-list>
        <template v-for="item in navItems">
          <!-- TOP LEVEL can be holders or actions -->

          <!-- TOP LEVEL HOLDER -->
          <template v-if="!item.route">
            <v-list-group
              :key="item.key"
              :prepend-icon="item.icon"
              :value="false"
              :data-cy="item.testid"
            >
              <template v-slot:activator>
                <!--group activator -->
                <v-list-item-title>{{ $sock.t(item.title) }}</v-list-item-title>
              </template>

              <!-- TOP LEVEL HOLDER SUBITEMS -->
              <template v-for="subitem in item.navItems">
                <template v-if="!subitem.route">
                  <!-- SECOND LEVEL HOLDER -->
                  <div :key="subitem.key" class="pl-2">
                    <v-list-group
                      :key="subitem.key"
                      no-action
                      sub-group
                      :value="false"
                    >
                      <!-- Second level activator -->
                      <template v-slot:activator>
                        <v-list-item-content>
                          <v-list-item-title>{{
                            $sock.t(subitem.title)
                          }}</v-list-item-title>
                        </v-list-item-content>
                      </template>

                      <v-list-item
                        v-for="subsub in subitem.navItems"
                        :key="subsub.key"
                        :to="subsub.route"
                      >
                        <v-list-item-action>
                          <v-icon
                            v-if="subsub.icon"
                            :color="item.color ? item.color : ''"
                            >{{ subsub.icon }}</v-icon
                          >
                        </v-list-item-action>
                        <v-list-item-title
                          :v-text="$sock.t(subsub.title)"
                        ></v-list-item-title>
                      </v-list-item>
                      <!-- was end of v-list-group here -->
                    </v-list-group>
                  </div>
                </template>
                <template v-else>
                  <!-- SECOND LEVEL ACTION -->
                  <div :key="subitem.key" class="pl-3">
                    <v-list-item
                      :to="subitem.route"
                      :data-cy="'nav' + subitem.testid"
                    >
                      <v-list-item-action>
                        <v-icon
                          v-if="subitem.icon"
                          :color="item.color ? item.color : ''"
                          >{{ subitem.icon }}</v-icon
                        >
                      </v-list-item-action>
                      <v-list-item-content>
                        <v-list-item-title>{{
                          $sock.t(subitem.title)
                        }}</v-list-item-title>
                      </v-list-item-content>
                    </v-list-item>
                  </div>
                </template>
              </template>
            </v-list-group>
            <!-- END OF TOP LEVEL HOLDER -->
          </template>

          <!-- TOP LEVEL ACTION -->
          <template v-else>
            <div :key="item.key">
              <v-list-item :to="item.route" :data-cy="item.testid">
                <v-list-item-action v-if="item.icon">
                  <v-icon :color="item.color ? item.color : ''">{{
                    item.icon
                  }}</v-icon>
                </v-list-item-action>
                <v-list-item-content>
                  <v-list-item-title>{{
                    $sock.t(item.title)
                  }}</v-list-item-title>
                </v-list-item-content>
              </v-list-item>
            </div>
          </template>

          <!-- end of entire list -->
        </template>
      </v-list>
      <template v-slot:append>
        <div>
          <v-btn x-large block to="/login" data-cy="logout">
            <v-icon large left>$sockiSignOut</v-icon>
            <span class="ml-2 text-h6">{{ $sock.t("Logout") }}</span></v-btn
          >
        </div>
      </template>
    </v-navigation-drawer>
    <v-app-bar v-if="isAuthenticated" :color="appBar.color" dark fixed app>
      <v-app-bar-nav-icon
        data-cy="navicon"
        @click.stop="drawer = !drawer"
      ></v-app-bar-nav-icon>
      <v-toolbar-title class="ml-n5 ml-sm-0 pl-sm-4">
        <v-icon>{{ appBar.icon }}</v-icon>
        <span class="text-subtitle-2 ml-2 text-sm-h6 ml-sm-4">{{
          titleDisplay
        }}</span>
      </v-toolbar-title>
      <v-spacer></v-spacer>
      <!-- All users can see this, they may not be able to subscribe to notifications but they may see direct or system notifications for any account so this is always available -->
      <template>
        <v-btn text icon to="/home-notifications" data-cy="notification">
          <v-badge color="deep-purple" :value="newNotificationCount() > 0">
            <template v-slot:badge>
              {{ newNotificationCount() }}
            </template>
            <v-icon>$sockiBell</v-icon>
          </v-badge>
        </v-btn>
      </template>

      <v-toolbar-items>
        <template v-for="item in appBar.menuItems">
          <v-btn
            v-if="item.surface"
            :key="item.key"
            class="hidden-xs-only"
            icon
            :disabled="item.disabled"
            :data-cy="item.key"
            @click="clickMenuItem(item)"
          >
            <v-icon :color="item.color ? item.color : ''">
              {{ item.icon }}
            </v-icon>
          </v-btn>
        </template>

        <v-spacer></v-spacer>

        <v-menu float-left>
          <template v-slot:activator="{ on }">
            <v-btn text icon data-cy="contextmenu" v-on="on">
              <v-icon>$sockiEllipsisV</v-icon>
            </v-btn>
          </template>
          <!-- https://stackoverflow.com/questions/54904746/scrolling-list-in-vuetify -->
          <v-list style="max-height: 100vh" class="overflow-y-auto">
            <template v-for="(item, index) in appBar.menuItems">
              <v-subheader v-if="item.header" :key="index">
                {{ item.header }}
              </v-subheader>
              <v-divider
                v-else-if="item.divider"
                :key="index"
                :inset="item.inset"
              ></v-divider>
              <v-list-item
                v-else
                :key="item.key"
                :disabled="item.disabled"
                :href="item.href"
                :target="item.target"
                :class="{ 'hidden-sm-and-up': item.surface }"
                :data-cy="item.key"
                @click="clickMenuItem(item)"
              >
                <v-list-item-action>
                  <v-icon
                    v-if="item.icon"
                    :color="item.color ? item.color : ''"
                    >{{ item.icon }}</v-icon
                  >
                </v-list-item-action>
                <v-list-item-content>
                  <v-list-item-title>
                    <span v-if="item.notrans">{{ item.title }}</span>
                    <span v-else>{{ $sock.t(item.title) }}</span>
                  </v-list-item-title>
                </v-list-item-content>
              </v-list-item>
            </template>
          </v-list>
        </v-menu>
      </v-toolbar-items>
    </v-app-bar>
    <v-main>
      <v-container fluid class="my-8">
        <transition name="fade" mode="out-in" @after-leave="afterLeave">
          <router-view :key="$route.fullPath" class="view"></router-view>
        </transition>
      </v-container>
    </v-main>
  </v-app>
</template>
<script>
import gzconfirm from "./components/gzconfirm";
import gznotify from "./components/gznotify";
import openObjectHandler from "./api/open-object-handler";
import notifyPoll from "./api/notifypoll";
import { processLogout } from "./api/authutil";
export default {
  components: {
    gzconfirm,
    gznotify
  },
  props: {
    source: { type: String, default: null }
  },
  data() {
    return {
      drawer: null,
      appBar: {
        isMain: true,
        icon: "",
        title: "",
        helpUrl: "user-intro",
        menuItems: []
      },
      //pwa update
      //https://medium.com/@dougallrich/give-users-control-over-app-updates-in-vue-cli-3-pwas-20453aedc1f2
      refreshing: false,
      registration: null,
      updateExists: false
    };
  },
  computed: {
    isAuthenticated() {
      return this.$store.state.authenticated === true;
    },
    navItems() {
      return this.$store.state.navItems;
    },
    // helpUrl() {
    //   return window.$gz.api.helpUrl();
    // },
    titleDisplay() {
      if (this.appBar.title == null || this.appBar.title == "") {
        return null;
      }
      return this.appBar.title;
    }
  },
  async created() {
    //Don't call this unless there is a service worker (https or localhost only, not private network) or else vuetify goes snakey and things start breaking
    if (navigator.serviceWorker) {
      //pwa update
      //https://medium.com/@dougallrich/give-users-control-over-app-updates-in-vue-cli-3-pwas-20453aedc1f2
      document.addEventListener("swUpdated", await this.showRefreshUI, {
        once: true
      });

      //for the record, this is the breaking code if there is no serviceworker
      navigator.serviceWorker.addEventListener("controllerchange", () => {
        if (this.refreshing) return;
        this.refreshing = true;
        window.location.reload();
      });
    }

    //////////////////////////////////
    // WIRE UP
    // EVENT HANDLERS ON GZEVENTBUS
    //
    //
    window.$gz.menu.wireUpEventHandlers(this);
    window.$gz.dialog.wireUpEventHandlers(this);
    openObjectHandler.wireUpEventHandlers(this);
    window.$gz.translation.setVuetifyDefaultLanguageElements(this);
  },
  beforeDestroy() {
    //UNWIRE ALL EVENT HANDLERS FROM GZEVENTBUS
    window.$gz.eventBus.$off();
  },
  mounted() {
    const vm = this;

    vm.$vuetify.theme.dark = vm.$store.state.darkMode;
    vm.$root.$gzconfirm = vm.$refs.gzconfirm.open;
    vm.$root.$gznotify = vm.$refs.gznotify.addNotification;
    vm.$root.$gz = window.$gz;

    //direct open path?
    let toPath = window.location.pathname;

    if (toPath != undefined && toPath.length > 4 && !toPath.includes("login")) {
      //must be at least 4 to be a valid Sockeye url
      window.$gz.store.commit(
        "logItem",
        `App::Mounted - preset path presented: ${toPath}`
      );
    } else {
      toPath = undefined;
    }

    const isReset = toPath && toPath.includes("home-reset");
    if (isReset && vm.$store.state.authenticated) {
      processLogout();
    }

    //redirect to login if not authenticated
    if (!vm.$store.state.authenticated && !isReset) {
      //If a direct open path was being used but user is not logged in this will catch it
      //otherwise they will just go on to that path directly

      if (toPath != undefined) {
        vm.$router.push({
          name: "login",
          params: {
            topath: window.location.pathname,
            search: window.location.search
          }
        });
      } else {
        vm.$router.push({
          name: "login",
          params: {
            search: window.location.search
          }
        });
      }
    }
    //RELOAD / REFRESH HANDLING
    //Restart notification polling due to refresh?
    if (window.$gz.store.state.authenticated) {
      notifyPoll.startPolling();
    }

    //FUTURE: If need to detect a reload, this works reliably
    //OK if here then is this a reliable way to detect a reload or refresh or re-open of the app from a closed window but still authenticated?
  },
  methods: {
    afterLeave() {
      this.$root.$emit("triggerScroll");
    },
    clickMenuItem(item) {
      window.$gz.eventBus.$emit("menu-click", item);
    },
    newNotificationCount() {
      return this.$store.state.newNotificationCount;
    },
    test() {
      alert("App.vue::test() method");
    },
    //PWA update
    async showRefreshUI(e) {
      this.registration = e.detail;
      this.updateExists = true;

      //Ok, if not logged in just force the update immediately
      if (!this.isAuthenticated) {
        this.refreshApp();
        return;
      }

      //User is logged in offer to update in a dialog with translated text
      const dialogResult = await window.$gz.dialog.confirmGeneric(
        "UpdateAvailable"
      );
      if (dialogResult == false) {
        return;
      }
      this.refreshApp();
    },
    refreshApp() {
      this.updateExists = false;
      if (!this.registration || !this.registration.waiting) {
        return;
      }
      this.registration.waiting.postMessage("skipWaiting");
      //todo clear stale data here?
      //maybe needs better control, i.e. conditionally clear only if needs to and then force re-login after
    }
  }
};
</script>
