<template>
  <div class="progress-diagram no-margin-bottom">
    <div
      class="columns no-margin-bottom progress-diagram-bar"
      style="margin: 0"
      @click="miniProgresDiagram = !miniProgresDiagram"
    >
      <div class="column is-three-fifths">
        <div class="title-is-4 section-title" style="display: inline;">
          <ios-git-branch-icon
            style="font-size: 1.2rem; display: inline-flex; position: relative; top: 3px"
          />
          Progress tracking
        </div>
        <div class="tiny-text" style="display: inline; margin-left: 2rem">
          <span class="light-text" style="margin-left: 1rem">Viewing analysis state </span>
          <span class="bold-text"> {{ activeCommit.title }} </span>
          <span class="light-text" style="margin-left: 10px"> on branch </span>
          <span class="bold-text"> {{ activeBranch.title }}</span
          >.
          <span v-if="!miniProgresDiagram" style="margin-left: 10px" @click.stop>
            <b-switch size="is-small" type="is-dark" v-model="highlightCommitsInReport" @click.stop>
              Highlight analysis states included in report
            </b-switch></span
          >
        </div>
      </div>
      <div v-if="!miniProgresDiagram" class="column">
        <div class="section-title">
          Branch detail
        </div>
      </div>
      <div v-else class="column">
        <div class="section-title">
          <!-- <b-button size="is-small" outlined @click="isCreateCommitModalActive = true">
            New analysis state
          </b-button> -->
        </div>
      </div>
      <div v-if="!miniProgresDiagram" class="column" style="display: flex">
        <div class="section-title" style="margin-left: 2rem">
          Analysis state detail
        </div>
      </div>
      <div v-else class="column" style="display: flex; padding: 0.5rem">
        <div class="section-title" style="margin-left: 2rem">
          <b-button
            size="is-small"
            type="is-info"
            outlined
            @click="isCreateCommitModalActive = true"
          >
            Save analysis state
          </b-button>
          <b-button
            size="is-small"
            outlined
            @click="isCreateNoteModalActive = true"
            style="margin-left: 0.5rem"
          >
            Add note
          </b-button>
        </div>
      </div>
      <div style="text-align: right; padding: 0.5rem">
        <font-awesome-icon
          :icon="miniProgresDiagram ? 'chevron-up' : 'chevron-down'"
          size="sm"
          class="font-awesome-icon"
          style="cursor: pointer"
        />
      </div>
    </div>
    <div v-if="!miniProgresDiagram" class="columns no-margin-bottom">
      <div class="column is-full">
        <div class="columns" style="margin-left: 0">
          <!-- Progress Tracking Diagram -->
          <div class="column is-three-fifths progress-tree-wrapper">
            <div class="tree-diagram-wrapper">
              <Timeline
                :start="firstCommitDate"
                :end="lastCommitDate"
                :newNotificationTime="newNotificationTime"
              />
              <TreeDiagram
                :commits="commits"
                :branches="branches"
                :branch-row-height="20"
                :active-commit-id="workspace.mainCommitId"
                :active-branch-id="workspace.mainBranchId"
                :show-wip-commit="isOnLastCommit && !activeBranch.closed"
                :newNotificationTime="newNotificationTime"
                :second-commit-id="workspace.secondaryCommitId"
                :visMode="visMode"
                :highlightCommitsInReport="highlightCommitsInReport"
                @commit-dblclick="switchToCommitAndBranch"
                @commit-for-comparison="displaySecondNetwork"
                @branch-dblclick="checkoutLatestCommit"
                @create-branch="isCreateBranchModalActive = true"
                @open-state-modal="isCreateCommitModalActive = true"
                @open-note-modal="isCreateNoteModalActive = true"
              />
            </div>
          </div>
          <!-- Branch Detail -->
          <div class="column" style="border: none; z-index: 10">
            <BranchDetail :branch="activeBranch" @close-branch="$emit('close-branch')" />
          </div>
          <!-- Commit detail -->
          <div class="column" style="z-index: 10">
            <CommitDetail
              :commit="activeCommit"
              @switch-to-comparison="$emit('switch-to-comparison')"
            />
          </div>
        </div>

        <div class="modals">
          <b-modal
            :active.sync="isCreateBranchModalActive"
            has-modal-card
            trap-focus
            aria-role="dialog"
            aria-modal
          >
            <CreateBranchModal @save="saveBranchData" />
          </b-modal>
          <b-modal
            :active.sync="isCreateCommitModalActive"
            has-modal-card
            trap-focus
            aria-role="dialog"
            aria-modal
          >
            <CreateCommitModal @save="saveCommitData" />
          </b-modal>
          <b-modal
            :active.sync="isCreateNoteModalActive"
            has-modal-card
            trap-focus
            aria-role="dialog"
            aria-modal
          >
            <CreateNoteModal @save="saveNote($event)" />
          </b-modal>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { mapState, mapActions, mapGetters } from 'vuex'
import TreeDiagram from './components/TreeDiagram.vue'
import Timeline from './components/Timeline.vue'
// import DetailsCard from './components/DetailsCard.vue'
import BranchDetail from './components/BranchDetail.vue'
import CommitDetail from './components/CommitDetail.vue'
import CreateCommitModal from '@/components/Modals/CreateCommitModal.vue'
import CreateNoteModal from '@/components/Modals/CreateNoteModal.vue'
import CreateBranchModal from '@/components/Modals/CreateBranchModal.vue'

import { getCommitsOnPath } from '@/utils/progress-diagram'

export default {
  components: {
    TreeDiagram,
    Timeline,
    // DetailsCard,
    BranchDetail,
    CommitDetail,
    CreateCommitModal,
    CreateNoteModal,
    CreateBranchModal
  },
  props: {
    view: {
      type: String
    },
    visMode: {
      type: String
    }
  },
  data() {
    return {
      branchRowHeight: 20,
      mergeToBranch: 3, // temp for testing
      isCreateBranchModalActive: false,
      isCreateCommitModalActive: false,
      isCreateNoteModalActive: false,
      commitDetailId: null, // temp
      miniProgresDiagram: true,
      highlightCommitsInReport: false
    }
  },
  mounted() {
    this.miniProgresDiagram = this.view === 'overview'
  },
  computed: {
    ...mapState('workspace', ['branches', 'commits']),
    ...mapGetters('workspace', ['getBranchById', 'getCommitById', 'getNotificationTime']),
    ...mapState('auth', ['user']),

    newNotificationTime() {
      return this.getNotificationTime //(this.workspace.mainCommitId)
    },

    activeBranch() {
      return this.getBranchById(this.workspace.mainBranchId)
    },

    workspace() {
      return this.user.workspace
    },

    activeCommit() {
      return this.getCommitById(this.workspace.mainCommitId)
    },

    firstCommitDate() {
      return new Date(this.commits[0].timestamp)
    },

    lastCommitDate() {
      return new Date(this.commits[this.commits.length - 1].timestamp)
    },

    // Returns true if active commit is the last in active branch
    // -> display wip commit
    // -> allow creating commits in current branch
    isOnLastCommit() {
      return this.activeCommit.id === this.getLatestCommitIdOnBranch(this.activeBranch.id)
    }
  },
  methods: {
    ...mapActions('workspace', ['saveNote', 'saveCommit', 'saveBranch']),
    ...mapActions('auth', ['changeActiveWorkspace']),

    getCommitsOnPath,

    saveCommitData($event) {
      this.saveCommit({
        ...$event,
        branchId: this.activeBranch.id,
        previousCommitId: [this.workspace.mainCommitId]
      })
      this.isCreateCommitModalActive = false
    },

    saveBranchData($event) {
      this.saveBranch({
        ...$event,
        commits: this.getCommitsOnPath(this.branches, this.activeCommit)
      })
      this.isCreateBranchModalActive = false
    },

    // toast() {
    //   this.$buefy.toast.open('Chevron clicked')
    // }

    addCommitsToBranch(branchId, newMergeCommit) {
      let allCommits = [
        ...this.branches.find(b => b.id === newMergeCommit.previousCommitId[0]).commits,
        ...this.branches.find(b => b.id === newMergeCommit.previousCommitId[1]).commits
      ]
      this.updateBranch({ branchId, commits: new Set(allCommits) })
    },

    getBranchIdFromCommit(id) {
      return this.commits.find(b => b.id === id).branchId
    },

    async switchToCommitAndBranch({ commitId, branchId }) {
      await this.changeActiveWorkspace({ mainBranchId: branchId, mainCommitId: commitId })
      this.$emit('commitChanged', { commitId, where: 'primary' })
    },

    checkoutLatestCommit(branchId) {
      this.switchToCommitAndBranch({
        commitId: this.getLatestCommitIdOnBranch(branchId),
        branchId
      })
    },

    getLatestCommitIdOnBranch(branchId) {
      return Math.max(...this.branches.find(b => b.id === branchId).commits)
      // return Math.max(...this.commits.filter(c => c.branchId === branchId).map(c => c.id))
    },

    // isOnLastCommit() {
    //   return (
    //     Math.max(...this.activeBranch.commits) === this.activeCommit.id &&
    //     (!this.activeBranch.closed || !this.activeBranch.merged)
    //   )
    // }

    mergeCurrentBranchInto(branchId) {
      branchId = Number(this.mergeToBranch)
      if (branchId === this.activeBranchId) {
        console.log('you cannot merge into the same branch')
        return
      }

      let branchToMergeTo = this.branches.find(b => b.id === branchId)
      // active branch is being merged
      let branchToBeMerged = this.activeBranch

      // commit from branch to merge to
      let mergeFromCommit1 = this.getLastCommitInBranch(branchId)
      // commit from branch that is going to be merged
      let mergeFromCommit2 = this.activeCommit

      // TO DO call merge operation on data

      let newCommit = {
        id: this.getNewCommitId(),
        type: 'merge-commit',
        originalBranchId: branchId,
        mergedBranchId: this.activeBranchId,
        belongsToBranches: [branchId, this.activeBranchId],
        time: 55 + this.getNewCommitId() * 5, // temp attribute to easily mock it's position in the tree-diagram
        timestamp: '2020-01-29-12-35-00',
        author: 'John Doe',
        commitMsg: 'Merge.',
        snapshotId: this.getNewCommitId(),
        inReport: true,
        userDefined: true,
        previousCommitId: [mergeFromCommit1.id, mergeFromCommit2.id]
      }
      this.commits.push(newCommit)
      branchToMergeTo.commits.push(newCommit.id)

      // update belongsToBranches for commits and commits list for branches
      this.getCommitsOnPathTill(mergeFromCommit2.id).forEach(c => {
        if (!c.belongsToBranches.includes(branchId)) {
          c.belongsToBranches.push(branchId)
        }
        branchToMergeTo.commits.push(c.id)
      })
      console.log(branchToBeMerged.commits)
      this.removeDuplicates(branchToBeMerged.commits)
      console.log(branchToBeMerged.commits)
      branchToBeMerged.merged = true
      this.switchToCommitAndBranch(newCommit.id)
    },

    getLastCommitIdInBranch(branchId) {
      let branchCommits = this.branches.find(b => b.id === branchId).commits
      return Math.max(...branchCommits)
    },
    getLastCommitInBranch(branchId) {
      return this.commits.find(c => c.id === this.getLastCommitIdInBranch(branchId))
    },
    getCommitsOnPathTill(commitId) {
      let commitIdsOnPath = this.getCommitIdsOnPathTill(commitId)
      return this.commits.filter(c => commitIdsOnPath.includes(c.id))
    },
    getCommitIdsOnPathTill(commitId) {
      let lastCommit = this.commits.find(c => c.id === commitId)

      let commits = []
      lastCommit.belongsToBranches.forEach(b_id => {
        let currBranch = this.branches.find(b => b.id === b_id)
        commits.push(...currBranch.commits)
      })
      commits = commits.filter(c => c <= commitId)
      this.removeDuplicates(commits)
      return commits
    },
    // doesn't need to be in this component. Or?
    removeDuplicates(array) {
      array.splice(0, array.length, ...new Set(array))
    },
    getNewCommitId() {
      return Math.max(...this.commits.map(c => c.id)) + 1
    },
    getNewBranchId() {
      return Math.max(...this.branches.map(b => b.id)) + 1
    },

    getBranchObject(branchId) {
      return this.branches.find(b => b.id === branchId)
    },

    getBranchCommitObjects(branchId) {
      let commitIds = this.getBranchObject(branchId).commits

      let commitObjects = []
      commitIds.forEach(c_id => {
        commitObjects.push(this.commits.find(c => c.id === c_id))
      })
      return commitObjects
    },

    getPathTill(commitId) {
      let commit = this.commits.find(c => c.id === commitId)
      console.log(commit)
      let branchId = commit.belongsToBranches[0]
      console.log(branchId)
      console.log(
        this.commits
          .filter(c => c.belongsToBranches.find(b => b === branchId))
          .filter(c => c.id <= commitId)
      )

      return this.commits
        .filter(c => c.belongsToBranches.find(b => b == branchId))
        .filter(c => c.id <= commitId)
    },
    getBranchCommitNodes(branch) {
      // let commitIds = this.branches.find(b => b.id == branchId).commits
      let commitIds = branch.commits
      let nodesOnPath = []
      commitIds.forEach(c => {
        nodesOnPath.push(this.nodes.find(n => n.commitId == c))
      })
      return nodesOnPath
    },
    getBranchPathLinks(branch) {
      // let commitIds = this.branches.find(b => b.id == branchId).commits
      let commitIds = branch.commits
      let linksOnPath = []
      commitIds.forEach(c => {
        linksOnPath.push(this.links.find(l => l.targetId === c))
      })
      return linksOnPath
    },
    highlightPathTill(commitId) {
      this.commits.find(c => c.id === commitId)
      this.getPathTill(commitId).forEach(c => (c.hoverHighlight = true))
    },

    async displaySecondNetwork(commitId) {
      await this.changeActiveWorkspace({ secondaryCommitId: commitId })
      this.$emit('commitChanged', { commitId, where: 'secondary' })
    }
  }
}
</script>

<style lang="sass" scoped>
$stroke-width-default: 1
$stroke-width-highlight: 2

h1
  font-weight: $section-title-font-weight
  font-size: $section-title-font-size
  color: $primary-text-color
  margin-bottom: 0.5rem

h6
  color: $primary-text-color
  font-weight: 600
  font-size: 0.95em
  margin-bottom: 0.2em
  margin-right: 1em

.progress-diagram
  background-color: #fffe
  // padding: 1rem 2.25rem 1rem
  position: absolute
  border-radius: 1rem 1rem 0 0
  bottom: 0
  width: 78%
  max-height: 20rem
  // margin-bottom: 0

.progress-diagram-bar
  background-color: #fafafa
  padding: 0 1rem
  border-radius: 1rem 1rem 0 0
  box-shadow: 0px -10px 10px -10px rgba(119,119,119,0.1)
  cursor: pointer
  &:hover
    background-color: #f5f5f5

.progress-diagram-menu
  margin-left: 1rem
  margin-bottom: 1rem

.tree-diagram-wrapper
  position: relative
  // margin-left: 0.5rem

.progress-tree-wrapper
  overflow-y: auto
  overflow-x: auto
  padding-top: 3rem
  max-height: 17rem

.section-title
  font-weight: 600
  font-size: 0.75rem
  text-transform: uppercase
  letter-spacing: 0.1rem
  color: #919191

.no-margin-bottom
  margin-bottom: 0
</style>
