<template>
  <v-card>
    <v-card-title>
      <span class="title">
        Students
      </span>
      <student-list-reverse-mapper class="ml-4"/>
      <v-spacer/>
      <v-text-field
        append-icon="search"
        label="Search"
        single-line
        hide-details
        v-model="search"
      ></v-text-field>
      <v-card-actions>
        <v-btn icon @click="refresh"><v-icon>refresh</v-icon></v-btn>
        <student-list-menu/>
      </v-card-actions>
    </v-card-title>
    <v-data-table
      :headers="dynamicHeaders"
      :items="studentListItems"
      :search="search"
      :pagination.sync="pagination"
      :loading="loading"
      item-key="name"
      hide-actions
    >
      <template slot="headers" slot-scope="props">
        <tr>
          <th
            v-for="(header, i) in props.headers" :key="i"
            :class="['column sortable', pagination.descending ? 'desc' : 'asc', header.value === pagination.sortBy ? 'active' : '']"
            style="padding: 0;"
            @click="changeSort(header.value)"
          >
            <v-icon>arrow_upward</v-icon>
            {{ header.text }}
          </th>
        </tr>
      </template>
      <template slot="items" slot-scope="props">
        <tr>
          <td>
            <v-btn small icon @click="props.expanded = !props.expanded">
              <v-icon v-if="props.expanded">keyboard_arrow_up</v-icon>
              <v-icon v-else>keyboard_arrow_down</v-icon>
            </v-btn>
            {{props.item.name}}
            <v-tooltip top>
              <template slot="activator">
                <v-icon small v-if="!props.item.is_active">lock</v-icon>
                <v-icon small v-else>lock_open</v-icon>
              </template>
              <span v-if="!props.item.is_active">Student doesn't have access.</span>
              <span v-else>Student has access.</span>
            </v-tooltip>
          </td>
          <td
            v-for="type in submissionTypeHeaders"
            style="padding: 0"
            :key="type.pk"
            class="text-xs-right"
          >
            <v-btn
              small round outline class="submission-button"
              exact
              v-if="props.item[type.pk]"
              :to="{name: 'submission-side-view', params: {
                studentPk: props.item.pk,
                submissionPk: props.item[type.pk].pk
               }}"
              :color="props.item[type.pk].final ? 'green darken-2' : 'grey'"
            >
              {{props.item[type.pk].score}}
            </v-btn>
            <span v-else>N.A</span>
          </td>
          <td
            style="padding: 0 15px;"
            class="text-xs-right"
          >{{props.item.total}}</td>
        </tr>
      </template>
      <template slot="expand" slot-scope="props">
        <v-card flat>
          <v-card-text>
            <v-btn @click="changeActiveStatus(props.item)">
              {{props.item.is_active ? 'Revoke access' : 'Grant access'}}
            </v-btn>
            <ul class="student-info-list">
              <li>
                <b>Modul:</b> {{props.item.exam}}
              </li>
              <li>
                <b>MatrikelNr:</b> {{props.item.matrikel_no}}
              </li>
            </ul>
          </v-card-text>
        </v-card>
      </template>
    </v-data-table>
  </v-card>
</template>

<script>
import {mapActions, mapState} from 'vuex'
import StudentListMenu from '@/components/student_list/StudentListMenu'
import StudentListReverseMapper from '@/components/student_list/StudentListReverseMapper'
import { changeActiveForUser } from '@/api'

export default {
  components: {
    StudentListReverseMapper,
    StudentListMenu},
  name: 'student-list',
  data () {
    return {
      loading: true,
      search: '',
      pagination: {
        sortBy: 'name',
        rowsPerPage: Infinity
      },
      staticHeaders: [
        {
          text: 'Name',
          align: 'left',
          value: 'name'
        }
      ]
    }
  },
  computed: {
    ...mapState([
      'students'
    ]),
    submissionTypeHeaders () {
      const subTypes = Object.values(this.$store.state.submissionTypes)
      return subTypes.map(type => {
        return {
          pk: type.pk,
          text: type.name.substr(0, 5),
          value: `${type.pk}.score`,
          align: 'right'
        }
      })
    },
    dynamicHeaders () {
      const totalScoreHeader = {
        text: 'Total',
        align: 'right',
        value: 'total'
      }
      let headers = this.staticHeaders.concat(this.submissionTypeHeaders)
      headers.push(totalScoreHeader)
      return headers
    },
    studentListItems () {
      if (!this.loading) {
        return Object.values(this.students).map(student => {
          return {
            pk: student.pk,
            user: student.user,
            user_pk: student.user_pk,
            exam: student.exam,
            name: student.name,
            is_active: student.is_active,
            matrikel_no: student.matrikel_no,
            ...this.reduceArrToDict(student.submissions, 'type'),
            total: this.sumSubmissionScores(student.submissions)
          }
        })
      }
    }
  },
  methods: {
    ...mapActions([
      'getStudents'
    ]),
    reduceArrToDict (arr, key) {
      return arr.reduce((acc, curr) => {
        const keyInDict = curr[key]
        acc[keyInDict] = curr
        return acc
      }, {})
    },
    changeActiveStatus (student) {
      changeActiveForUser(student.user_pk, !student.is_active).then(() => {
        this.getStudents({studentPks: [student.pk], fields: ['is_active']})
      }).catch(() => {
        this.$notify({
          title: 'Error',
          text: `Unable to change active status of ${student.user}`,
          type: 'error'
        })
      })
    },
    sumSubmissionScores (submissions) {
      return submissions.reduce((acc, curr) => {
        if (curr.score) {
          acc += curr.score
        }
        return acc
      }, 0)
    },
    changeSort (column) {
      if (this.pagination.sortBy === column) {
        this.pagination.descending = !this.pagination.descending
      } else {
        this.pagination.sortBy = column
        this.pagination.descending = false
      }
    },
    refresh (opts = {silent: false}) {
      if (!opts.silent) {
        this.loading = true
      }
      this.getStudents().then(() => { this.loading = false })
    }
  },
  created () {
    this.getStudents().then(() => { this.loading = false })
  }
}
</script>

<style scoped>
  .submission-button {
    min-width: 40px;
  }
  .student-info-list li {
    display: inline;
    margin-right: 20px;
  }
  .student-info-list {
    display: inline;
  }
</style>