<i18n>
{
  "en": {
    "alreadyBuiling": "The iPXE building process not finished",
    "bios": "BIOS",
    "branchName": "Branch Name",
    "buildingIpxe": "Building iPXE ...",
    "buildIpxe": "Build iPXE",
    "buildTargetsLabel": "Build Targets",
    "cancelIpxe": "Cancel iPXE",
    "certificateSaved": "Certificate saved successfully",
    "cleaningIpxe": "Cleaning iPXE ...",
    "cleanIpxe": "Clean iPXE",
    "console": "console.h",
    "consoleSaved": "console.h saved successfully",
    "efi": "EFI",
    "general": "general.h",
    "generalSaved": "general.h saved successfully",
    "ipxe": "iPXE",
    "output": "Output",
    "parameters": "Parameters",
    "repoUrl": "Repository URL",
    "script": "Embedded script (EMBED=)",
    "scripts": "Scripts",
    "scriptSaved": "Embedded script saved successfully",
    "scrollDown": "Go to the bottom",
    "trust": "Embedded certificate (TRUST=)"
  },
  "de": {
    "alreadyBuiling": "Der iPXE build-Prozess ist noch nicht abgeschlossen",
    "bios": "BIOS",
    "branchName": "Branch Name",
    "buildingIpxe": "iPXE wird gebaut ...",
    "buildIpxe": "iPXE bauen",
    "buildTargetsLabel": "Build Targets",
    "cancelIpxe": "iPXE stoppen",
    "certificateSaved": "Zertifikat wurde erfolgreich gespeichert",
    "console": "console.h",
    "consoleSaved": "console.h wurde erfolgreich gespeichert",
    "cleaningIpxe": "iPXE wird aufgeräumt ..",
    "cleanIpxe": "iPXE aufräumen",
    "efi": "EFI",
    "general": "general.h",
    "generalSaved": "general.h wurde erfolgreich gespeichert",
    "ipxe": "iPXE",
    "output": "Output",
    "parameters": "Parameter",
    "repoUrl": "Repository URL",
    "script": "Eingebettetes Skript (EMBED=)",
    "scripts": "Skripte",
    "scriptSaved": "Eingebettetes Skript wurde erfolgreich gespeichert",
    "scrollDown": "Gehe nach unten",
    "trust": "Eingebettetes Zertifikat (TRUST=)"
  }
}
</i18n>

<template>
  <div class="">
    <v-subheader>{{ $t('parameters') }}</v-subheader>
    <v-card>
      <v-card-text>
        <v-layout wrap>

          <v-flex lg5 md8 sm8 xs12 order-lg1 order-md1 order-sm1 order-xs2>
            <v-layout column>
              <div class="info-input">
                <div class="info-heading"><v-icon>label</v-icon><span>{{ $t('repoUrl') }}</span></div>
                <div v-if="!editParametersMode" class="info-text">{{ repoUrl }}</div>
                <v-text-field v-else v-model="repoUrl" class="info-text pa-0 tutorial-element tutorial-no-border label-far-left" style="--label-number: '1'" hide-details></v-text-field>
              </div>
            </v-layout>
          </v-flex>

          <v-flex lg4 md6 sm6 xs12 order-lg2 order-md4 order-sm4 order-xs3>
            <v-layout column>
              <div class="info-input">
                <div class="info-heading"><v-icon>label</v-icon><span>{{ $t('branchName') }}</span></div>
                <div v-if="!editParametersMode" class="info-text">{{ branchName }}</div>
                <v-text-field v-else v-model="branchName" class="info-text pa-0 tutorial-element tutorial-no-border label-far-left" style="--label-number: '2'" hide-details></v-text-field>
              </div>
            </v-layout>
          </v-flex>

          <v-flex lg9 md6 sm6 xs12 order-lg4 order-md3 order-sm3 order-xs4>
            <v-layout column class="tutorial-element tutorial-no-border" style="--label-number: '3'">
              <div class="info-input">
                <div class="info-heading"><v-icon>my_location</v-icon><span>{{ $t('buildTargetsLabel') }}</span></div>

                <div v-if="!editParametersMode" class="non-selectable info-text">
                  <v-chip v-for="target in buildTargets" :key="target" small>
                    <span class="chip-text">{{ target }}</span>
                  </v-chip>
                </div>
                <v-select
                  class="info-text"
                  v-else-if="editParametersMode && !allowCustomTargets"
                  v-model="buildTargets"
                  :items=targets
                  multiple
                  small-chips
                  menu-props="offsetY"
                >
                </v-select>
                <v-combobox
                  class="info-text"
                  v-else-if="editParametersMode && allowCustomTargets"
                  v-model="buildTargets"
                  :items="targets"
                  :search-input.sync="search"
                  hide-selected
                  multiple
                  persistent-hint
                  small-chips
                  deletable-chips
                  hide-details
                  dense
                  style="padding: 0px"
                  @input="createTarget"
                >
                  <template #no-data>
                    <v-list-item>
                      <v-list-item-content>
                        <v-list-item-title>
                          No results matching "<strong>{{ search }}</strong>". Press <kbd>enter</kbd> to create a new one
                        </v-list-item-title>
                      </v-list-item-content>
                    </v-list-item>
                  </template>

                  <template #item="{ index, item }">
                    <v-list-item-content>
                      {{ item }}
                    </v-list-item-content>
                    <v-list-item-action @click.stop>
                      <v-btn icon @click.stop.prevent="deleteTarget(item)">
                        <v-icon color="error">delete</v-icon>
                      </v-btn>
                    </v-list-item-action>
                  </template>

                </v-combobox>

              </div>
            </v-layout>
          </v-flex>

          <v-flex v-if="!editParametersMode" lg3 md4 sm4 xs12 order-lg3 order-md2 order-sm2 order-xs1 class="text-right">
            <div class="info-input">
              <v-btn color="primary" text @click="editParameters" class="info-buttons">
                <v-icon left>create</v-icon>{{ $t('edit') }}
              </v-btn>
            </div>
          </v-flex>

          <v-flex v-else lg3 md4 sm4 xs12 order-lg3 order-md2 order-sm2 order-xs1 class="text-right">
            <div class="info-input">
                <v-btn color="primary" text @click="cancelEditParameters" class="info-buttons">{{ $t('cancel') }}</v-btn>
                <v-btn color="primary" @click="submitParameters" class="info-buttons">
                  <v-icon left>save</v-icon>{{ $t('save') }}
                </v-btn>
            </div>
          </v-flex>

        </v-layout>
      </v-card-text>
    </v-card>

    <v-subheader>{{ $t('output') }}</v-subheader>
    <!--
    <v-card v-on:wheel="manualScroll">
      <div>
        <RecycleScroller :items="log" ref="log" :item-size="21" style="height: 588px;">
          <div slot-scope="{ item }" style="height: 21px;">
            <pre :class="item.status + '--text'" style="margin-bottom: 0px"><span>{{ item.date }} {{ item.msg }}</span></pre>
          </div>
        </RecycleScroller>
      </div>
    </v-card>
    -->

    <!-- Recycle Scroller or not?! One of them ^v has to go! -->
    <v-card class="terminal" ref="log" v-on:wheel="manualScroll" style="padding-left: 0px">
      <template v-for="(entry, index) in log">
        <pre :class="entry.status + '--text'" style="margin-bottom: 0px;" :key="index"><span>{{ entry.date }} {{ entry.msg }}</span></pre>
      </template>
    </v-card>

    <div class="scroll-overlay non-selectable" v-if="!autoscroll" @click="toTheBottom" style="cursor: pointer">
      <div style="height: 100%; display: flex; align-items: center;">
        <v-icon style="margin-right: 10px">vertical_align_bottom</v-icon><pre>{{ $t('scrollDown') }}</pre>
      </div>
    </div>

    <div class="text-right">
      <v-btn text color="error" @click="cleanIpxe" :disabled=disableButtons class="ma-2 tutorial-element label-left" style="--label-number: '1'"><v-icon left>delete</v-icon>{{ $t('cleanIpxe') }}</v-btn>
      <v-btn text color="warning" @click="cancelIpxe" :disabled=!disableButtons class="ma-2 tutorial-element label-bottom" style="--label-number: '2'"><v-icon left>cancel</v-icon>{{ $t('cancelIpxe') }}</v-btn>
      <v-btn text color="primary" @click="buildIpxe" :disabled=disableButtons class="ma-2 tutorial-element label-right" style="--label-number: '3'"><v-icon left>gavel</v-icon>{{ $t('buildIpxe') }}</v-btn>
    </div>
    <v-subheader>{{ $t('scripts') }}</v-subheader>
    <v-card class="tabbar-card subtabs" :color="tabsColor">
      <v-tabs v-model="tabs" grow :dark="tabsDark" :background-color="tabsColor" :slider-color="tabsSliderColor" hide-slider class="tutorial-element tutorial-border label-bottom" style="--label-number: '1'">
          <v-tab :class="tabs === 0 ? 'primary--text' : ''"><v-icon class="tabbar-tabicon" :color="tabs === 0 ? 'primary' : ''">description</v-icon>{{ $t('script') }}</v-tab>
          <v-tab :class="tabs === 1 ? 'primary--text' : ''"><v-icon class="tabbar-tabicon" :color="tabs === 1 ? 'primary' : ''">description</v-icon>{{ $t('trust') }}</v-tab>
          <v-tab :class="tabs === 2 ? 'primary--text' : ''"><v-icon class="tabbar-tabicon" :color="tabs === 2 ? 'primary' : ''">description</v-icon>{{ $t('general') }}</v-tab>
          <v-tab :class="tabs === 3 ? 'primary--text' : ''"><v-icon class="tabbar-tabicon" :color="tabs === 3 ? 'primary' : ''">description</v-icon>{{ $t('console') }}</v-tab>
      </v-tabs>
    </v-card>
    <v-tabs-items v-model="tabs" style="padding-bottom: 12px"> <!--20px-->
      <v-tab-item :transition="false" :reverse-transition="false">
        <div slot="header">{{ $t('script') }}</div>
        <v-card>
          <codemirror class="script-editor" ref="script" v-model="script"></codemirror>
          <div class="text-right">
            <v-btn class="ma-2" text color="error" @click="undo('script')"><v-icon left>undo</v-icon>{{ $t('undo') }}</v-btn>
            <v-btn class="ma-2" text color="success" @click="redo('script')"><v-icon left>redo</v-icon>{{ $t('redo') }}</v-btn>
            <v-btn class="ma-2" color="primary" @click="save('script')"><v-icon left>save</v-icon>{{ $t('save') }}</v-btn>
          </div>
        </v-card>
      </v-tab-item>
      <v-tab-item :transition="false" :reverse-transition="false">
        <div slot="header">{{ $t('trust') }}</div>
        <v-card>
          <codemirror class="script-editor" ref="certificate" v-model="certificate"></codemirror>
          <div class="text-right">
            <v-btn class="ma-2" text color="error" @click="undo('certificate')"><v-icon left>undo</v-icon>{{ $t('undo') }}</v-btn>
            <v-btn class="ma-2" text color="success" @click="redo('certificate')"><v-icon left>redo</v-icon>{{ $t('redo') }}</v-btn>
            <v-btn class="ma-2" color="primary" @click="save('certificate')"><v-icon left>save</v-icon>{{ $t('save') }}</v-btn>
          </div>
        </v-card>
      </v-tab-item>
      <v-tab-item :transition="false" :reverse-transition="false">
        <div slot="header">{{ $t('general') }}</div>
        <v-card>
          <codemirror class="script-editor" ref="general" v-model="general"></codemirror>
          <div class="text-right">
            <v-btn class="ma-2" text color="error" @click="undo('general')"><v-icon left>undo</v-icon>{{ $t('undo') }}</v-btn>
            <v-btn class="ma-2" text color="success" @click="redo('general')"><v-icon left>redo</v-icon>{{ $t('redo') }}</v-btn>
            <v-btn class="ma-2" color="primary" @click="save('general')"><v-icon left>save</v-icon>{{ $t('save') }}</v-btn>
          </div>
        </v-card>
      </v-tab-item>
      <v-tab-item :transition="false" :reverse-transition="false">
        <div slot="header">{{ $t('console') }}</div>
        <v-card>
          <codemirror class="script-editor" ref="console" v-model="console"></codemirror>
          <div class="text-right">
            <v-btn class="ma-2" text color="error" @click="undo('console')"><v-icon left>undo</v-icon>{{ $t('undo') }}</v-btn>
            <v-btn class="ma-2" text color="success" @click="redo('console')"><v-icon left>redo</v-icon>{{ $t('redo') }}</v-btn>
            <v-btn class="ma-2" color="primary" @click="save('console')"><v-icon left>save</v-icon>{{ $t('save') }}</v-btn>
          </div>
        </v-card>
      </v-tab-item>
    </v-tabs-items>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  name: 'IpxeBuilderModuleConfig',
  components: {
  },
  data () {
    return {
      allowCustomTargets: false,
      autoscroll: true,
      buildTargets: [],
      branchName: '',
      certificate: '',
      console: '',
      disableButtons: false,
      editParametersMode: false,
      general: '',
      log: [],
      repoUrl: '',
      script: '',
      search: '',
      tabs: 0,
      targets: []
    }
  },
  computed: {
    ...mapGetters(['tabsDark', 'tabsColor', 'tabsSliderColor'])
  },
  methods: {
    createTarget (list) {
      const index = list.length - 1
      if (this.allowCustomTargets && this.targets.indexOf(list[index]) === -1) this.targets.push(list[index])
    },
    deleteTarget (item) {
      const index = this.targets.indexOf(item)
      if (this.allowCustomTargets) this.targets.splice(index, 1)
    },
    save (apiPath) {
      this.$http.put('/api/ipxe/' + apiPath, { data: this[apiPath] }).then(result => {
        const saveMsg = apiPath + 'Saved'
        if (result.data.status === 'SUCCESS') this.$snackbar({ color: 'success', text: this.$tc(saveMsg) })
        else this.$snackbar({ color: 'error', text: result.data.error })
      })
    },
    undo (element) {
      this.$refs[element].codemirror.undo()
    },
    redo (element) {
      this.$refs[element].codemirror.redo()
    },
    buildIpxe () {
      this.$http.get('/api/ipxe/build').then(result => {
        if (result.data.status === 'SUCCESS') this.$snackbar({ color: 'primary', text: this.$tc('buildingIpxe') })
        else if (result.data.status === 'ALREADY_BUILDING') this.$snackbar({ color: 'error', text: this.$tc('alreadyBuiling') })
      })
    },
    cleanIpxe () {
      this.$http.get('/api/ipxe/clean').then(result => {
        if (result.data.status === 'SUCCESS') this.$snackbar({ color: 'primary', text: this.$tc('cleaningIpxe') })
        else if (result.data.status === 'ALREADY_BUILDING') this.$snackbar({ color: 'error', text: this.$tc('alreadyBuiling') })
      })
    },
    cancelIpxe () {
      this.$http.get('/api/ipxe/cancel').then(result => {
        if (result.data.status === 'SUCCESS') this.$snackbar({ color: 'primary', text: this.$tc('cleaningIpxe') }) // TODO:
      })
    },
    manualScroll (event) {
      if (event.deltaY < 0) this.autoscroll = false
      else if (this.$refs.log.$el.scrollTop + 800 >= this.$refs.log.$el.scrollHeight) this.autoscroll = true
    },
    toTheBottom () {
      this.autoscroll = true
    },
    editParameters () {
      this.editParametersMode = true
    },
    cancelEditParameters () {
      this.editParametersMode = false
    },
    getParameters () {
      this.$http.get('/api/ipxe/config').then(config => {
        config = config.data
        this.branchName = config.branch
        this.repoUrl = config.repository
        this.targets = config.targets.list
        this.buildTargets = config.targets.build
        this.allowCustomTargets = config.targets.custom
      })
    },
    submitParameters () {
      const data = { repository: this.repoUrl, branch: this.branchName, buildTargets: this.buildTargets, targetList: this.targets }
      this.$http.post('/api/ipxe/config', data).then(response => {
        this.editParametersMode = false
      })
    }
  },
  created () {
    this.getParameters()

    // Load the data.
    this.$http.get('/api/ipxe/script').then(result => {
      this.script = result.data
    })
    this.$http.get('/api/ipxe/certificate').then(result => {
      this.certificate = result.data
    })
    this.$http.get('/api/ipxe/general').then(result => {
      this.general = result.data
    })
    this.$http.get('/api/ipxe/console').then(result => {
      this.console = result.data
    })

    this.$http.get('/api/ipxe/log?max=500').then(result => {
      var lines = result.data.split('\n')
      for (var line in lines) {
        if (lines[line] === '') continue
        var attr = lines[line].split('\t')
        this.log.push({ id: this.log.length, date: attr[0], status: attr[1], msg: attr[2] })
      }
    })

    // Socket io event listeners
    this.$socket.on('log', entry => {
      this.log.push({ id: this.log.length, msg: entry.msg, status: entry.status, date: entry.date })
    })

    // Disable the buttons if a building process is running.
    this.$http.get('/api/ipxe/status').then(result => {
      this.disableButtons = result.data.data
    })

    // this.$socket.on('inProgress', inProgress => {
    //  this.disableButtons = inProgress
    // })
  },
  updated () {
    if (this.autoscroll) {
      // Use this instead for the virtual scroller
      this.$refs.log.$el.scrollTop = this.$refs.log.$el.scrollHeight
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
  .scroll-overlay {
    position: absolute;
    margin-top: -35px;
    width: 100%;
    display: flex;
    justify-content: center;
    background-color: rgba(0, 0, 0, .5);
    height: 35px;
  }
  .terminal {
    padding: 12px 24px 12px 24px;
    height: 588px;
    overflow: auto;
  }

  .script-editor >>> .CodeMirror {
    height: calc(90vh - 160px);
  }
  .subtabs {
    z-index: 1;
  }

  .info-input {
    margin: 20px;
  }

  .info-heading > span {
    margin-left: 10px;
  }

  .info-buttons {
    margin: 0;
  }

  .info-text {
    margin-left: 34px;
    font-family: 'Roboto Mono';
  }
</style>
