<template>
  <div>
    <v-tooltip bottom>
      <v-btn :color="exportColor"
             slot="activator"
             @click="getCSVFileAndProcess"
      >
        export
        <v-icon>file_download</v-icon>
      </v-btn>
      <span v-if="corrected">All submissions have been corrected!</span>
      <span v-else>UNCORRECTED submissions left! Export will be incomplete.</span>
    </v-tooltip>
    <v-dialog v-model="mapFileDialog" max-width="30vw">
      <v-card>
        <v-card-title class="title">
          Currently no student mapping file is selected
        </v-card-title>
        <v-card-text>
          If you select a mapping file, the anonymized data
          will be mapped back automatically and locally on your machine.

          <v-layout row align-center>
            <file-select v-model="mapFile" display-text="Select map file" class="ma-3"/>
            <span>Without the mapping, the data will still be obfuscated.</span>
          </v-layout>

          <v-card-actions>
            <v-btn
              flat color="blue lighten-2"
              @click="mapFileDialog = false"
            >close</v-btn>
            <v-spacer/>
            <v-btn flat outline @click="getCSVFileAndProcess"
            >{{mapFile ? 'Download and apply mapping' : 'Download without mapping'}}</v-btn>
          </v-card-actions>
        </v-card-text>
      </v-card>
    </v-dialog>
  </div>
</template>

<script>
  import {mapGetters} from 'vuex'
  import ax from '@/api'
  import FileSelect from '@/components/util/FileSelect'
  import { mut } from '@/store/mutations'
  import { parseCSVMapMixin } from '@/components/mixins/mixins'

  export default {
    components: {FileSelect},
    name: 'data-export',
    mixins: [parseCSVMapMixin],
    data () {
      return {
        fileReader: new FileReader(),
        mapFile: null,
        mapFileDialog: false
      }
    },
    computed: {
      ...mapGetters([
        'corrected'
      ]),
      exportColor () {
        return this.corrected ? 'green darken-1' : 'red lighten-1'
      },
      downloadUrl () {
        let url = ''
        if (process.env.NODE_ENV === 'production') {
          const baseUrl = `https://${window.location.host}${window.location.pathname}`.replace(/\/+$/, '')
          url = `${baseUrl}/api/export/csv`
        } else {
          url = 'http://localhost:8000/api/export/csv/'
        }
        return url
      },
      studentMap () {
        return this.$store.state.studentMap
      },
      mapFileLoaded () {
        return Object.keys(this.studentMap).length > 0
      }
    },
    methods: {
      readMapFileAndCommit (callback) {
        this.fileReader.onload = event => {
          const studentMap = this.parseCSVMap(event.target.result)
          this.$store.commit(mut.SET_STUDENT_MAP, studentMap)
          callback()
        }
        this.fileReader.readAsText(this.mapFile)
      },
      async download () {
        const response = await ax.get(this.downloadUrl, {responseType: 'blob'})
        return new Blob([response.data], { type: 'text/csv' })
      },
      CSVToJson (csvString) {
        const lines = csvString.split('\n')
        const headers = lines.shift().split(';')
        return lines
          .filter(line => !!line)  // remove empty strings
          .map(line => {
            const lineItems = line.split(';')
            return headers.reduce((acc, curr, i) => {
              acc[headers[i]] = lineItems[i]
              return acc
            }, {})
          })
      },
      jsonToCSV (data) {
        const headerLine = Object.keys(data[0]).reduce((acc, curr) => {
          return acc ? `${acc};${curr}` : `${curr}`
        }, '')
        const lines = data.map(studentData => {
          return Object.values(studentData).reduce((acc, curr) => {
            return acc ? `${acc};${curr}` : `${curr}`
          }, '')
        })
        return headerLine + lines.reduce((acc, curr) => {
          return `${acc}\n${curr}`
        }, '') + '\n'     // add trailing newline
      },
      mapStudentData (students) {
        return students.map(studentData => {
          return {
            ...studentData,
            Matrikel: this.$store.state.studentMap[studentData.Matrikel].matrikel_no,
            Name: this.$store.state.studentMap[studentData.Matrikel].name
          }
        })
      },
      getMappedCSV () {
        this.download().then(blobData => {
          if (this.mapFileLoaded) {
            this.fileReader.onload = event => {
              const jsonData = this.CSVToJson(event.target.result)
              const mappedData = this.mapStudentData(jsonData)
              const csvData = this.jsonToCSV(mappedData)
              const mappedBlobData = new Blob([csvData], { type: 'text/csv' })
              window.open(window.URL.createObjectURL(mappedBlobData))
            }
            this.fileReader.readAsText(blobData)
          } else {
            window.open(window.URL.createObjectURL(blobData))
          }
        })
      },
      getCSVFileAndProcess () {
        if (!this.mapFileLoaded && !this.mapFileDialog) {
          this.mapFileDialog = true
        } else {
          if (this.mapFile) {
            this.readMapFileAndCommit(this.getMappedCSV)
          } else {
            this.getMappedCSV()
          }
        }
      }
    }

  }
</script>

<style scoped>
  #export-link {
    color: #000;
    text-decoration: none;
  }
</style>