import '@babel/polyfill';
import Vue from 'vue';
import VueVimeoPlayer from 'vue-vimeo-player';
import apolloClientFactory from './graphql/client';
import VueApollo from 'vue-apollo';
import App from './App.vue';
import { postLoginRedirectUrlKey, router } from './router';
import store from '@/store/index';
import VueScrollTo from 'vue-scrollto';
import autoGrow from '@/directives/auto-grow';
import clickOutside from '@/directives/click-outside';
import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
import VueModal from '@/plugins/modal';
import VueRemoveEdges from '@/plugins/edges';
import VueMatomo from 'vue-matomo';
import { joiningClass, loginRequired, unauthorizedAccess } from '@/router/guards';
import flavorPlugin from '@/plugins/flavor';
import log from 'loglevel';

window.log = log; // make log available in app when built, to change log level: log.setLevel('debug')

Vue.config.productionTip = false;
const isProduction = process.env.NODE_ENV === 'production';

const logLevel = isProduction ? 'error' : 'warn';

log.setDefaultLevel(logLevel);

Vue.use(VueModal);
Vue.use(VueRemoveEdges);
Vue.use(VueApollo);
Vue.use(VueVimeoPlayer);

Vue.use(VueScrollTo, {
  duration: 500,
  easing: 'ease-out',
  offset: -50,
});

Vue.use(flavorPlugin);

if (process.env.MATOMO_HOST) {
  Vue.use(VueMatomo, {
    host: process.env.MATOMO_HOST,
    siteId: process.env.MATOMO_SITE_ID,
    router: router,
  });
}

Vue.directive('click-outside', clickOutside);
Vue.directive('auto-grow', autoGrow);

const publicApolloClient = apolloClientFactory('/api/graphql-public/', null);
const privateApolloClient = apolloClientFactory('/api/graphql/', networkErrorCallback);

const apolloProvider = new VueApollo({
  clients: {
    publicClient: publicApolloClient,
  },
  defaultClient: privateApolloClient,
});

/* guards */

function redirectUsersWithoutValidLicense() {
  return privateApolloClient
    .query({
      query: ME_QUERY,
    })
    .then(({ data }) => data.me.expiryDate == null);
}

function redirectStudentsWithoutClass() {
  return privateApolloClient
    .query({
      query: ME_QUERY,
    })
    .then(({ data }) => data.me.schoolClasses.length === 0 && !data.me.isTeacher);
}

function redirectUsersToOnboarding() {
  return privateApolloClient
    .query({
      query: ME_QUERY,
    })
    .then(({ data }) => !data.me.onboardingVisited);
}

function networkErrorCallback(statusCode) {
  if (statusCode === 402) {
    log.debug('status code 402, redirecting');
    router.push({ name: 'licenseActivation' });
  }
}

router.beforeEach(async (to, from, next) => {
  log.debug('navigation guard called', to, from);
  if (to.path === '/logout') {
    log.debug('logout', to);
    publicApolloClient.resetStore();
    if (process.env.LOGOUT_REDIRECT_URL) {
      location.replace(`https://sso.hep-verlag.ch/logout?return_to=${process.env.LOGOUT_REDIRECT_URL}`);
      next(false);
      return;
    } else {
      next({ name: 'hello' });
      return;
    }
  }

  if (unauthorizedAccess(to)) {
    log.debug('unauthorized', to);
    const postLoginRedirectionUrl = to.path;
    const redirectUrl = `/hello/`;

    if (window.localStorage) {
      localStorage.setItem(postLoginRedirectUrlKey, postLoginRedirectionUrl);
    }

    log.debug('redirecting to hello', to);
    next(redirectUrl);
    return;
  }

  if (to.name && to.name !== 'licenseActivation' && loginRequired(to) && (await redirectUsersWithoutValidLicense())) {
    log.debug('redirecting to licenseActivation', to, null);
    console.log('redirecting to licenseActivation', to, null);
    next({ name: 'licenseActivation' });
    return;
  }

  if (!joiningClass(to) && loginRequired(to) && (await redirectStudentsWithoutClass())) {
    log.debug('redirecting to join-class', to);
    log.debug('await redirectStudentsWithoutClass()', await redirectStudentsWithoutClass());
    next({ name: 'join-class' });
    return;
  }

  if (
    to.name &&
    to.name.indexOf('onboarding') === -1 &&
    !joiningClass(to) &&
    loginRequired(to) &&
    (await redirectUsersToOnboarding())
  ) {
    log.debug('redirecting to onboarding-start', to);
    next({ name: 'onboarding-start' });
    return;
  }

  log.debug('End of Guard reached', to);
  next();
});

/* eslint-disable no-new */
new Vue({
  el: '#app',
  store,
  router,
  apolloProvider,
  render: (h) => h(App),
});
