<template>
  <v-tour
    name="exampleMode"
    :steps="steps"
    :callbacks="callbacks"
    :options="{
      highlight: true,
      enabledNavigationKeys: {
        ESCAPE: false,
        ARROW_RIGHT: true,
        ARROW_LEFT: false,
      },
      labels: {
        buttonPrevious: 'Fast-forward to results',
        buttonSkip: 'End example',
        buttonNext: 'Next',
        buttonStop: 'Finish',
      },
    }"
  >
  </v-tour>
</template>

<script>
import { mapGetters, mapMutations } from "vuex";
import _ from "lodash";
class Act {
  constructor({ id, content, before, params, target }) {
    this.id = id;
    this.content = content;
    this.before = before;
    this.params = _.merge({ enableScrolling: false }, params);
    this._target = target;
  }

  get elem() {
    return document.querySelector(this.target);
  }

  input(text) {
    this.elem.value = text;
    this.elem.dispatchEvent(new CustomEvent("input", { bubbles: true }));
    this.elem.dispatchEvent(new Event("input", { bubbles: true }));
  }

  get target() {
    return this._target ?? `[example-act='${this.id}']`;
  }
}

function wait() {
  return new Promise((resolve) => {
    requestAnimationFrame(resolve);
  });
}

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

function waitForAnimationEnd(selector) {
  return new Promise((resolve) => {
    const animated = document.querySelector(selector);
    console.log(animated);
    debugger;
    animated.addEventListener("transitionend", () => {
      debugger;
      return resolve();
    });
  });
}

function checkElement(selector) {
  if (document.querySelector(selector) === null) {
    return wait().then(() => checkElement(selector));
  } else {
    return Promise.resolve(true);
  }
}

export default {
  data() {
    return {
      steps: [
        new Act({
          id: "intro",
          content:
            "Welcome to the guided example for LoopGrafter - a web-based tool designed to provide assistance and guidance in the process of transferring one or more loops in between homologous proteins.",
        }),
        new Act({
          id: "protein-showcase",
          content:
            "For this example, we are using proteins 6G75:A and 2PSF:B. If you would like to go through the example by yourself, you can load these proteins from RCSB database on the 'Submit new job' screen.",
        }),
        new Act({
          id: "scaffold-protein-adjustment",
          content:
            "The DSSP assignment in residues 150 - 155 (a small 3:10 helix) is not the one desired and it can be modified to coil. Select the residues",
          before: () => {
            document
              .querySelector("[example-act='scaffold-download-confirm']")
              ?.click();
            return checkElement("[example-act='scaffold-protein-adjustment']");
          },
          params: {
            placement: "top",
          },
        }),
        new Act({
          id: "make-coil-button",
          content: "and set them to coil",
          before: () => {
            document
              .querySelector("[example-act='scaffold-protein-adjustment']")
              .dispatchEvent(new CustomEvent("change", { bubbles: true }));
          },
        }),
        new Act({
          id: "3d",
          content: "The both proteins can be inspected here",
        }),
        new Act({
          id: "pipeline-viz",
          content:
            "The progress in the loop grafting pipeline can be monitored here",
        }),
        new Act({
          id: "loop-exploration-open",
          content:
            "The first step (Secondary Structures refinment) is now completed. To continue with the second one (Loop exploration), click on the header to unfold the step interface.",
          before: () => {
            return checkElement("[example-act='loop-exploration-open']");
          },
        }),
        new Act({
          id: "scaffold-download-loops",
          content:
            "Click here to calculate the scaffold protein loops and their geometries.",
          before: () => {
            document
              .querySelector("[example-act='loop-exploration-open'] button")
              ?.click();
            return sleep(500);
          },
        }),
        new Act({
          id: "scaffold-loop-rep",
          content:
            "An overview of all the loops on the scaffold protein can be seen here.",
          before: () => {
            document
              .querySelector("[example-act='scaffold-download-loops']")
              ?.click();
            return checkElement("#le-6G75_A_135");
          },
        }),
        new Act({
          id: "insert-download-loops",
          content:
            "Click here to calculate the insert protein loops and their geometries.",
        }),
        new Act({
          id: "view-interesting-loops",
          content:
            "The attributes of the scaffold loops and their selection status for grafting can be seen here at each step.",
          before: () => {
            document
              .querySelector("[example-act='insert-download-loops']")
              ?.click();
            return checkElement("#le-2PSF_B_137");
          },
        }),
        new Act({
          id: "select-scaffold-loop",
          content:
            "Loops can be inspected up closer. Click on the loop that was initially modified (different secondary structure assignment) to obtain a detailed view of it.",
          target: "#le-6G75_A_135",
        }),
        new Act({
          id: "select-insert-loop",
          content:
            "Loops from the insert protein can also be inspected this way. Selecting loops from both scaffold and insert allows for direct comparison of those loops.",
          target: "#le-2PSF_B_137",
        }),
        new Act({
          id: "loop-comparison-1",
          content:
            "The extent of the loops, their secondary structure assignment and numerical values for geometry can be observed here;",
        }),
        new Act({
          id: "loop-comparison-2",
          content:
            "and a graphical representation of their geometries here, providing an easy way of comparison.",
        }),
        new Act({
          id: "flexibility-open",
          content:
            "To continue with the third step (Flexibility evaluation), click on the header to unfold the step interface.",
        }),
        new Act({
          id: "flexibility-select",
          content:
            "Gausian and Anisotropic Network Models can be used in addition to B-factors obtained from the PDB file fro the assessment. Additionally, custom values can also be inputted by clicking on the right side arrow.",
          before: () => {
            document
              .querySelector("[example-act='flexibility-open'] button")
              ?.click();
            return sleep(500);
          },
        }),
        new Act({
          id: "flexibility-select-confirm",
          content: "Click to proceed.",
        }),
        new Act({
          id: "flexibility-exploration",
          content:
            "The calculated flexibility for all scaffold loops is shown colour-coded here, being more flexible loops warm-coloured and the less flexible ones shown in cold colours.",
          before: () => {
            document
              .querySelector("[example-act='flexibility-select-confirm']")
              ?.click();
            return checkElement("[example-act='flexibility-exploration']");
          },
        }),
        new Act({
          id: "flexibility-exploration-methods",
          content:
            "The correlation in between the different used methods for flexibility assessment can be seen here.",
        }),
        new Act({
          id: "flexibility-ss",
          content:
            "The flexibility values can also be shown for secondary structure elements or individual residues.",
          params: {
            placement: "top",
          },
        }),
        new Act({
          id: "flexibility-select-loop",
          content:
            "This loop looks interesting, because joins a relatively static region of the protein (left, bluish colour) with a very flexible one (right, bright orange colour). Add it to the list of candidate loops using the + button.",
          target: "#fe-anm-6G75_A_135",
        }),
        new Act({
          id: "view-interesting-loops",
          content:
            "The scaffold list now shows the selected loop as a candidate loop for grafting.",
          before: () => {
            document
              .querySelector("#fe-anm-6G75_A_135 > .toggle-button.remove")
              ?.click();
            return checkElement("[example-act='flexibility-exploration']");
          },
        }),
        new Act({
          id: "ccors-open",
          content:
            "To continue with the fourth step (Motion-correlation evaluation), click on the header to unfold the step interface.",
        }),
        new Act({
          id: "ccors-exploration",
          content:
            "The motion cross-correlation between the currently selected candidate loops and the remaining ones in the scaffold protein can be seen here.",
          params: {
            placement: "left",
          },
          before: () => {
            document
              .querySelector("[example-act='ccors-open'] button")
              ?.click();
            return sleep(500);
          },
        }),

        new Act({
          id: "ccors-select-loop",
          content:
            "The flexible regions of this loop show a good cross-correlation with the loop already selected. Add it to the candidate list by clicking on the + button.",
          target: "#ce-6G75_A_210",
        }),
        new Act({
          id: "pairing-open",
          content:
            "To continue with the fifth step (Loop pairing), click on the header to unfold the step interface.",
          before: () => {
            document.querySelector("#ce-6G75_A_210 .toggle-button")?.click();
            return checkElement("[example-act='pairing-open']");
          },
        }),
        new Act({
          id: "pairing-start-13",
          content:
            "Click on the 'Attempt automatic assignment' button to try to automatically pair selected scaffold loops with appropriate insert loops",
          target: "#autoLoopPairing",
          before: () => {
            document
              .querySelector("[example-act='pairing-open'] button")
              ?.click();
            return sleep(500);
          },
        }),
        new Act({
          id: "pairing-geometry-135",
          content:
            "The geometrical similarity of the paired loops can be reviewed again in here.",
          target: "#pairing-charts-6G75_A_135",
          before: () => {
            document.querySelector("#autoLoopPairing")?.click();
            return checkElement("#pairing-charts-6G75_A_135");
          },
        }),
        new Act({
          id: "grafting-open",
          content:
            "To continue with the sixth step (Loop grafting), click on the header to unfold the step interface.",
        }),
        new Act({
          id: "graft-start",
          content:
            "Submit the selected and paired loops for pregrafting to obtain the grafting sequences.",
          before: () => {
            document
              .querySelector("[example-act='grafting-open'] button")
              ?.click();
            return checkElement("[example-act='grafting-open']");
          },
        }),
        new Act({
          id: "download-seq",
          content: "You may obtain them as a JSON file here.",
          before: () => {
            document.querySelector("[example-act='graft-start']")?.click();
            return checkElement("[example-act='download-seq']");
          },
        }),
        new Act({
          id: "graft-final",
          content:
            "And the process is done! Click here to start the model computation. The calculation on this example (which yields over 400 solutions) typically needs less than one hour. Other experiments may take longer.  Due to computational restrictions, the maximum number of solutions is limited to 1000.",
        }),
      ],

      callbacks: {
        onNextStep: this.handleStep,
        onSkip: () => {
          this.$router.push({
            name: "new",
          });
        },
        onPreviousStep: () => {
          this.$router.push({
            name: "results-view",
            params: { jobId: "exemplary-example" },
          });
          this.$tours["exampleMode"].stop();
        },
        onFinish: () => {
          this.$router.push({
            name: "results-check",
            params: { jobId: "exemplary-example" },
          });
        },
      },
    };
  },

  methods: {
    ...mapMutations(["setExampleMode", "setToken"]),
    startExample() {
      this.setExampleMode(true);
      this.$tours["exampleMode"].start();
    },
    handleStep(step) {
      let act = this.steps[step];
      Promise.all(this.getCurrentAwaitables).then(() => {
        switch (act.id) {
          case "make-coil-button":
            act.elem?.click();
            break;
          case "select-scaffold-loop":
            act.elem?.click();
            break;
          case "select-insert-loop":
            act.elem?.click();
            break;
          case "flexibility-open":
            act.elem?.click();
            break;
          case "flexibility-select-loop":
            document.querySelector("#fe-anm-6g75_A_13 > .remove")?.click();
            break;
          case "ccors-open":
            act.elem?.click();
            break;
          case "ccors-select-loop":
            document.querySelector("#ce-6g75_A_18 .remove")?.click();
            break;

          case "grafting-open":
            act.elem?.click();
            break;
          //stop forgetting the break before default
          default:
            break;
        }
      });
    },
  },
  computed: {
    ...mapGetters(["getCurrentAwaitables"]),
  },

  created() {
    if (this.$route.meta.activateExample) {
      this.setToken("exemplary-example");
    }
  },

  mounted() {
    this.$nextTick().then(() => {
      if (this.$route.meta.activateExample) {
        this.startExample();
      }
    });
  },
  // watch: {
  //   $route: {
  //     handler: function (to) {
  //       if (to.meta.activateExample) {
  //         this.$nextTick().then(() => {});
  //       }
  //     },
  //     immediate: true,
  //   },
  // },
};
</script>

<style>
.v-tour__target--highlighted {
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.3) !important;
}
.v-tour__target--highlighted[example-act="flexibility-select"],
.v-tour__target--highlighted[example-act="view-interesting-loops"],
.v-tour__target--highlighted[example-act="scaffold-loop-rep"],
.v-tour__target--highlighted[example-act="loop-comparison-1"],
.v-tour__target--highlighted[example-act="flexibility-exploration"],
.v-tour__target--highlighted[example-act="intro"],
.v-tour__target--highlighted[example-act="protein-showcase"],
.v-tour__target--highlighted[example-act="ccors-exploration"] {
  pointer-events: none;
}

.v-step {
  background: var(--accent) !important;
}

.v-step__arrow {
  border-color: var(--accent) !important;
}
</style>