<!-- src/components/RecursiveList.vue -->

<!-- Usage:

--->

<template lang='pug'>
  v-container
    v-row.justify-space-between
      div
        v-tabs(centered)
          v-tab(v-for='page, i in sections' :key='i')
            v-tab(@click.prevent="show=page" v-bind:class="[{onPage: show===page}, {offPage: show!==page}]") 
              span(v-if='options.icons && options.icons[page]')
                v-icon {{options.icons[page]}}
                span(v-if="$vuetify.breakpoint.mdAndUp") &nbsp; &nbsp; {{page}}
              span(v-else) {{page}}
      div(v-if='!options.autoupdate')
        span(v-for='f in formats' style='padding-right: 50px; float: right font-size: 12px' :key='f')
          a( href='#' @click="setFormat(f)")
            b.text-xs(v-if='myFormat === f' style='font-size: 12px') {{f}}
            span.text-xs(v-else style='font-size: 12px') {{f}}
    br
    hr
    p &nbsp;
    div(v-for='page, j in sections' :key='j')
      v-card(v-show="show===page")
        v-card-text
          RecursiveList(
            :title='title' 
            :list='split_list[page]' 
            :section='page' 
            :preset='preset' 
            :options='options' 
            :format='myFormat'
            :access='access' 
            :onSelect='mySelect' 
            :onDeSelect='myDeSelect' 
            :onChange='myChange' 
            :saveOnChange='saveOnChange' 
            :onClick='onClick' 
            :remoteSelect='remoteSelect' 
            :remoteDeSelect='remoteDeSelect' 
            :debug='debug'
            :saved='saved'
          )
      v-card(v-show='!show')
        v-card-text
          h4 List is divided into {{sections.length}} primary categories.
          h4 Click on a category above to view / select within each
    div(v-if='saveOnSubmit && editCount.total')
      p &nbsp;
      div(style='flex-direction: column')
        v-btn.btn-primary(v-if='saveOnSubmit' @click='saveAll') {{saveOnSubmitButton}}
        div(v-for='section, name in edits' :key='"Add" + name' style='text-align: left')
          b(v-if='editCount[name] && editCount[name].Added') 
            i Added {{name}} [{{editCount[name].Added}}]: &nbsp; &nbsp;
            span.text-success {{section.turnedOnName.join(', ')}};
        div(v-for='section, name in edits' :key='"Rmv" +name' style='text-align: left')
          b(v-if='editCount[name] && editCount[name].Removed') 
            i Removed {{name}} [{{editCount[name].Removed}}]: &nbsp; &nbsp;
            span.text-warning {{section.turnedOffName.join(', ')}};
      p &nbsp;
    hr
    div(v-if='debug')
      h6 Sections: {{sections}}
      h6 Current: {{current}}
      h6 Preset: {{preset}}
</template>

<script>
import RecursiveList from './RecursiveList'
import {Roarr as logger} from 'roarr'

export default {
  components: {
    RecursiveList
  },
  data () {
      return {
          split_list: {},
          sections: [],
          subTypes: {},
          show: '',
          formats: ['Tree', 'List'],
          current: [],
          pendingList: [],
          edits: {},
          editCount: {},
          myFormat: '',
          Local: {},
          saved: 0,
          preset: [],
          fullList: [],
          Section: {}
      }
  },
  props: {
    list: {
        type: Array
    },
    localList: {
      type: Array
    },
    mapData: {
      // map Object data (may include personalized variations)
      type: Function
    },
    mapAlias: {
      // Generic mapping of Object name - (not including personalized information)
      type: Function 
    },
    //   Following are passed on directly
    title: {
      type: String
    },
    onClick: {
        type: Function
    },
    onChange: {
      type: Function
    },
    onSelect: {
        type: Function
    },
    onDeSelect: {
        type: Function
    },
    saveOnChange: {
        type: Function
    },
    saveOnSubmit: {
        type: Function
    },
    remoteSelect: {
      type: Object
    },
    remoteDeSelect: {
      type: Object
    },
    format: {
        type: String
    },
    access: {
        type: String
    },
    options: {
        type: Object,
        default () { return {
          selectable: true
        }}
    },
    debug: {
      type: Boolean,
      default: false
    }
  },
  created: function () {
    if (this.format) {
      this.setFormat(this.format)
    } else if (this.options.format) {
      this.setFormat(this.options.format)
    } else if (!this.format && this.options.autoupdate) {
      this.setFormat('Tree')
    } else {
      this.setFormat('List')
    }
    this.$set(this, 'preset', this.localList)
    
    if (this.options.page) {
      this.show = this.options.page
    }

    this.regenerate('creation', true)
  },
  computed: {
    saveOnSubmitButton: function () {
      return this.options.saveAllButton || 'Save All Changes'
    }
  },
  methods: {
    saveAll: function () {
      if (this.saveOnSubmit) {
        logger.debug('save on submit....')
        this.saveOnSubmit(this.pendingList, this.edits)
        this.resetEdits()
        
        this.$set(this, 'preset', this.pendingList)
        // this.regenerate('saveOnSubmit', true)
      }
    },
    resetEdits: function () {
      this.saved++ // indicate to Recursive list that the edits have been made
      this.edits = {}
      this.editCount = {}
    },
    setFormat: function (f) {
      this.$set(this, 'myFormat', '')
      this.$set(this, 'myFormat', f) // toggled to force refresh on watch
    },
    async regenerate (context, reset) {
      logger.debug(context)
      if (reset) {
        this.fullList = await this.parseList()
        logger.debug('parsed group list into sections: ' + this.sections.join(', '))
      }
      if (this.preset) {
        await this.parseLocal(reset)
        logger.debug('parsed personal list of ' + this.preset.length)
      }
    },
    myChange: function (list, edits, section) {
      logger.log(section + ' Edits: ' + JSON.stringify(edits))
      logger.log(section + ' List: ' + JSON.stringify(list))

      if (this.autoupdate) {
        this.current = this.pendingList
      }

      this.edits[section] = edits
      logger.log('All Edits: ' + JSON.stringify(this.edits))
      logger.log('Current: ' + JSON.stringify(this.current))
      logger.log('Pending: ' + JSON.stringify(this.pendingList))

      const resetList = this.pendingList.filter(a => (a.section !== section))
      logger.debug("PENDING LIST: " + JSON.stringify(this.pendingList) + ' w/o ' + section + ' + ' + JSON.stringify(list))
      this.pendingList = resetList.concat(list)
      logger.debug("PENDING LIST ALONE: " + JSON.stringify(this.pendingList))

      var count = 0
      for (var i=0; i < this.sections.length; i++) {

        var edit = this.edits[this.sections[i]]
        if (edit) {
          this.$set(this.editCount, this.sections[i], {})
          this.$set(this.editCount[this.sections[i]], 'total', edit.turnedOn.length + edit.turnedOff.length || 0)
          this.$set(this.editCount[this.sections[i]], 'Added', edit.turnedOn.length || 0)
          this.$set(this.editCount[this.sections[i]], 'Removed', edit.turnedOff.length || 0)
          count = count + edit.turnedOn.length + edit.turnedOff.length
        }
      }

      this.$set(this.editCount, 'total', count)
      logger.log('Edit counts: ' + JSON.stringify(this.editCount))
      if (this.onChange) {
        this.onChange(this.pendingList, edits)
      }
    },
    mySelect: function (item) {
      // if (this.options.autoupdate) {
      logger.log('my Select ' + JSON.stringify(item))

      this.pendingList.push(item)

      logger.debug('+ updated list: ' + JSON.stringify(this.pendingList))

      if (this.onSelect) {
        this.onSelect(item)
      }
    },
    myDeSelect: function (item) {
      logger.log('my deselect ' + JSON.stringify(item))
      logger.debug(' previous list: ' + JSON.stringify(this.pendingList))

      this.pendingList = this.pendingList.filter(a => (a.id != item.id))

      logger.debug('- updated list: ' + JSON.stringify(this.pendingList))
    
      if (this.onDeselect) {
        this.onDeselect(item)
      }

    },
    parseLocal: function (reset) {
      const clone = JSON.parse(JSON.stringify(this.preset)) || []

      this.$set(this, 'Local', {}) // reset ...
      if (this.mapData) {
        // var atts = Object.keys(this.mapData)
        this.current = clone.map(a => this.mapData(a))
        logger.debug('cloned..')
        logger.debug(clone)

      } else {
        this.current = clone
      }

      for (var i = 0; i < this.current.length; i++) {
        var obj = this.current[i]
        if (obj && obj.id) {
          if (this.Section[obj.id]) {
            obj.section = this.Section[obj.id]
            this.$set(this.preset[i], 'section', this.Section[obj.id])
          }
          this.$set(this.Local, obj.id, obj)
        }
      }
      logger.debug('Mapped from personal data:' + JSON.stringify(this.Local))
      if (reset) {
        this.pendingList = this.current
        logger.debug('Current Pending List updated:' + JSON.stringify(this.current))
      } else {
        logger.debug('pending list remains: ' + JSON.stringify(this.pendingList))
      }
      return Promise.resolve()
    },
    parseList: function () {
      var fullList = this.list || []
      var split_recursive_list = {}
      var recursive_sections = []
      var subTypes = {}
      logger.debug('parse list of interests... found ' + fullList.length)
      // logger.debug('Local ' + JSON.stringify(this.Local))
      
      var inList = {}
      for (var i = 0; i < fullList.length; i++) {
        // var object = JSON.parse(JSON.stringify(fullList[i]))
        var object = fullList[i]

        var id = object.id
        var parent = object.parent_id
        var name = object.name

        var section = inList[parent] || name
        inList[id] = section

        if (this.mapAlias) {
          object.alias = this.mapAlias(object)
        }
        
        if (this.Local[object.id]) {
          object = this.Local[object.id]
        }
        object.section = section
        fullList[i].section = section

        if (parent && inList[parent]) {
          split_recursive_list[section].push(object)
          if (!subTypes[parent]) {
              subTypes[parent] = []
          }
          subTypes[parent].push({name: name, id: id})
        } else {
          split_recursive_list[section] = [object]
          recursive_sections.push(name)
        }

        this.$set(this.Section, object.id, section)
      }

      this.split_list = split_recursive_list
      this.sections = recursive_sections
      this.subTypes = subTypes
      
      return Promise.resolve(fullList)
    }
  },
  watch: {
    list: function () {
      logger.debug('updated list')
      this.regenerate('watch list', true)
    },
    split_list: function () {
      logger.debug('updated split list')
    },
    sections: function () {
      logger.log('updated sections ' + this.sections)
    },
    show: function () {
      logger.debug('changed section to ' + this.show)
      // logger.debug('split list: ' + JSON.stringify(this.split_list[this.show]))
      // this.regenerate()
    },
    localList: function () {
      logger.debug('changed localList list..')
      this.$set(this, 'preset', this.localList)
      this.regenerate('watch personal list', false)
    }
  }
}
</script>

<style scoped>
.text-warning {
  color: orange;
}
.text-success {
  color: green;
}
.btn-primary {
  background-color: green;
}
</style>
