<template>
  <div class="survey-page">
    <h1 class="survey-page__title">{{ title }}</h1>
    <survey :survey="survey"/>

    <solution
      :value="solution"
      v-if="showSolution"/>
    <div v-if="surveyComplete">
      <a
        class="button button--primary"
        @click="reopen">Übung bearbeiten</a>
    </div>
  </div>
</template>

<script>
  import * as SurveyVue from 'survey-vue';
  import {css} from '@/survey.config';
  import gql from 'graphql-tag';

  import SURVEY_QUERY from '@/graphql/gql/queries/surveyQuery.gql';
  import UPDATE_ANSWER from '@/graphql/gql/mutations/updateAnswer.gql';
  import Solution from '@/components/content-blocks/Solution';

  import {extractSurveySolutions} from '@/helpers/survey-solutions';
  import {isTeacher} from '@/helpers/is-teacher';

  import {meQuery} from '@/graphql/queries';

  const Survey = SurveyVue.Survey;

  const MODULE_QUERY = gql`
    query ModuleSolutions($id: ID) {
        module(id: $id) {
            solutionsEnabled
        }
    }
`;

  export default {
    props: ['id'],

    components: {
      Solution,
      Survey,
    },

    data() {
      return {
        survey: this.initSurvey(),
        title: '',
        module: {},
        completed: false,
        me: {
          permissions: [],
        },
        saveDisabled: false,
      };
    },

    computed: {
      surveyComplete() {
        return this.survey && this.survey.isCompleted;
      },
      showSolution() {
        return (this.module.solutionsEnabled || this.isTeacher) && !this.survey.isCompleted;
      },
      solution() {
        // todo: should this be done inside of Solution.vue?
        return {
          text: this.answers.reduce((previous, answer) => {
            if (!answer.answer) {
              return previous;
            }
            if (answer.type === 'matrix' || answer.type === 'checkbox') {
              // wrap all the answers inside li tags and convert to a single string
              const answerText = answer.answer.map(a => `<li class="solution-text__list-item">${a}</li>`).join('');
              return `
            ${previous}
            <h2 class="solution-text__heading">${answer.title}</h2>
            <ul class="solution-text__answer solution-text__list">${answerText}</ul>
            `;
            } else {
              return `
            ${previous}
             <h2 class="solution-text__heading">${answer.title}</h2>
             <p class="solution-text__answer">${answer.answer}</p>
             `;
            }
          }, ''),
        };
      },
      answers() {
        return this.survey.currentPage && this.survey.currentPage.elements
          ? this.survey.currentPage.elements.reduce(extractSurveySolutions, [])
          : [];
      },
      isTeacher() {
        return isTeacher(this);
      },
    },

    methods: {
      initSurvey(data, answers) {
        let survey = new SurveyVue.Model(data);
        const flatAnswers = {};
        for (let k in answers) {
          flatAnswers[k] = answers[k].answer;
        }
        this.$log.debug('flatAnswers', flatAnswers);
        this.$log.debug('data', survey.data);
        if (Object.keys(flatAnswers).length > 0) {
          // answers are not empty
          survey.data = flatAnswers;
        }

        const saveSurvey = (sender, {exit}) => {
          this.$log.debug('saving survey', sender);
          if (this.saveDisabled) {
            return;
          }

          this.completed = true;

          const data = {};

          for (let k in survey.data) {
            if (survey.data.hasOwnProperty(k)) {
              let question = sender.getQuestionByName(k);
              data[k] = {
                answer: survey.data[k],
                correct: question && question.correctAnswer ? question.correctAnswer : '',
              };
            }
          }
          if (Object.keys(data).length === 0) {
            // data is empty
            return;
          }
          const answer = {
            surveyId: this.id,
            data: JSON.stringify(data),
          };

          this.$apollo.mutate({
            mutation: UPDATE_ANSWER,
            variables: {
              input: {
                answer,
              },
            },
            update: (store, {data: {updateAnswer: {answer}}}) => {
              const query = SURVEY_QUERY;
              const variables = {id: this.id};
              const queryData = store.readQuery({query, variables});
              if (queryData.survey) {
                queryData.survey.answer = answer;
                store.writeQuery({query, variables, data: queryData});
              }
            },
          }).then(() => {
            if (exit) {
              this.$router.go(-1);
            }
          });
        };

        survey.onComplete.add((sender, options) => {
          saveSurvey(sender, {
            ...options,
            exit: true
          });
        });
        survey.onCurrentPageChanged.add(saveSurvey);

        survey.css = css;
        survey.locale = 'de';
        survey.showProgressBar = 'bottom';
        survey.pageNextText = 'Speichern & Weiter';
        this.$log.debug(survey.data);
        return survey;
      },
      reopen() {
        this.saveDisabled = true; // disable saving, because resetting triggers a page change which we don't want to save
        this.completed = false;
        let data = this.survey.data; // save the data
        this.survey.clear();
        this.survey.data = data; // reapply it
        this.saveDisabled = false;
      },
    },

    apollo: {
      survey: {
        query: SURVEY_QUERY,
        variables() {
          return {
            id: this.id,
          };
        },
        manual: true,
        result({data, loading, networkStatus}) {
          if (!loading) {
            let json = JSON.parse(data.survey.data);
            json.showTitle = false;
            let answer = {};
            if (data.survey.answer && data.survey.answer.data) {
              answer = JSON.parse(data.survey.answer.data);
            }

            if (!this.completed) {
              this.survey = this.initSurvey(json, answer);
            }
            this.title = json.title;
            const module = data.survey.module;

            this.$apollo.addSmartQuery('module', {
              query: MODULE_QUERY,
              variables: {
                id: module.id,
              },
            });
          }
        },
      },
      me: meQuery,
    },
  };
</script>

<style scoped lang="scss">
  @import "@/styles/_variables.scss";
  @import "@/styles/_mixins.scss";

  .survey-page {
    max-width: 800px;
    display: grid;
    grid-template-rows: auto 1fr;
    grid-auto-rows: auto;
    grid-row-gap: $large-spacing;
    justify-self: center;
    padding: 100px 0;
    width: 100%;

    &__title {
      @include meta-title;
      margin: 0;
    }
  }
</style>
