var crud = {
  data : function () {
    return {
      data: this.data,
      instance: this.instance
    }
  },
  methods: {
    create_back: function (row, callbackOK, callbackError) {
      try {
        let rows = JSON.parse(localStorage.getItem(this.instance))
        
        // Set next id
        row['id'] = Math.max(...rows.map(function ( obj ) { return obj['id'] })) + 1

        rows.push(row)
        this.saveData(rows)
        if (callbackOK) {
          callbackOK(row)
        }
      }
      catch (e) {
        if (callbackError) {
          callbackError({'errors':['cath_error']})
        }
      }
    },
    read_back: function (row, callbackOK, callbackError) {
      try {
        if (row) {
          // read one recrd
          let rows = JSON.parse(localStorage.getItem(this.instance))
          for (item of rows) {
            if (item['id'] == row['id']) {
              if (callbackOK) {
                callbackOK(item)
              }
              return
            }
          }
          // Nothing found
          if (callbackError) {
            callbackError({'errors':['nothing_found']})
          }
        }
        else {
          // read all records
          callbackOK(JSON.parse(localStorage.getItem(this.instance)))
        }
      }
      catch (e) {
        if (callbackError) {
          callbackError({'errors':['cath_error']})
        }
      }
    },
    update_back: function (row, callbackOK, callbackError) {
      try {
        let rows = JSON.parse(localStorage.getItem(this.instance))
        for (let index in rows) {
          if (rows[index]['id'] == row['id']) {
            rows[index] = row
            this.saveData(rows)
            if (callbackOK) {
              callbackOK(rows[index])
            }
          }
        }
      }
      catch (e) {
        if (callbackError) {
          callbackError({'errors':['cath_error']})
        }
      }
    },
    delete_back: function (row, callbackOK, callbackError) {
      try {
        let rows = JSON.parse(localStorage.getItem(this.instance))
        for (let index in rows) {
          if (rows[index]['id'] == row['id']) {
            rows.splice(index, 1)
            this.saveData(rows)
            if (callbackOK) {
              callbackOK({'result': 'OK'})
            }
          }
        }
      }
      catch (e) {
        if (callbackError) {
          callbackError({'errors':['cath_error']})
        }
      }
    },

    ///////////////////////////////////////////////////////
    //this method used only for local storage
    //this method not needed when you'll use real backend
    ///////////////////////////////////////////////////////
    saveData: function (rows) {
      localStorage.setItem(this.instance, JSON.stringify(rows))
    },
    ///////////////////////////////////////////////////////




  }
}

var crud_front = {
    methods: {
        create_front: function (row) {
            this.create_back(row, ()=>{
              this.data.push(row)
              app.notify({type: 'success', message: 'Created successfully'})
            })
          },
          read_front: function (row) {
            this.read_back(row, (response)=>{
              if (row) {
                // update row
                for (key in response) {
                  row[key] = response[key]
                }
              }
              else {
                // update data
                this.data = response
              }
            })
          },
          update_front: function (row) {
            this.update_back(row, ()=>{
              for (item of this.data) {
                if (item['id'] == row['id']) {
                  this.read_front(item)
                  app.notify({type: 'success', message: 'Saved successfully'})
                }
              }
            })
          },
          delete_front: function (row) {
            app.confirm('Delete ?').then(()=> {
              this.delete_back(row, ()=>{
                this.data.splice(this.data.indexOf(row), 1)
                app.notify({type: 'success', message: 'Deleted successfully'})
              });
            }).catch( function () {
            })
          },
          show_error: function(response) {
            console.log(response)
            app.notify({type: 'error', message: 'Something went wrong'})
          }
    }
}


var table = {
  props: ['rows', 'id', 'perpage', 'sumfields', 'pagestore'],
  data: function () {
    return {
      currentPage: 1,
      search: '',
      searchField: '',
      orderField: '',
      orderFieldType: '',
      orderReverse: false,
    }
  },
  computed: {
    pages () {
      if (typeof this.filteredRows == 'undefined') {
        return 0
      }
      else {
        return Math.ceil(this.filteredRows.length / this.perpage)
      }
    },

    filteredRows() {
      if (this.search == '')
        return this.sortedRows

      let rows = []
      let found = false
      let search = this.search.toLowerCase()
      for (let row of this.sortedRows) {
        found = false
        for (let col in row) {
          if (this.searchField == '' || this.searchField == col) {
            try {
              found = found || (row[col].toString().toLowerCase().search(search) > -1)
            }
            catch (e) {
            }
          }
        }
        if (found)
        rows.push(row)
      }
      return rows
    },

    sortedRows () {
      if (this.orderField == '')
        return this.rows

      let rows = this.rows.slice()
      rows = rows.sort((x, y) => {
        function compare (x, y, type) {
            function cook (d, type) {
              switch(type) {
                case 'number':
                  d = parseFloat(d)
                  break
                case 'float':
                  d = parseFloat(d)
                  break
                case 'date':
                  if (d.indexOf('.') == -1) {
                    d = new Date(d)
                  }
                  else {
                    if (d.indexOf(':') == -1) {
                      let DMY = d.split('.')
                      d = new Date(parseInt(DMY[2]), parseInt(DMY[1])-1, parseInt(DMY[0]), 0, 0, 0)
                    }
                  }
                  break
                case 'datetime':
                  if ( (d.indexOf(':') != -1) && (d.indexOf('.') != -1) ) {
                    let DT = d.split(' ')
                    let HMS = DT[0].split(':')
                    let DMY = DT[1].split('.')
                    d = new Date(parseInt(DMY[2]), parseInt(DMY[1])-1, parseInt(DMY[0]), parseInt(HMS[0]), parseInt(HMS[1]), parseInt(HMS[2]))
                  }
                  break

                default:
                  try {
                    d = d.toString().toLowerCase()
                  }
                  catch (err) {
                    d = ''
                  }
              }
              return d
            }
            x = cook(x, type)
            y = cook(y, type)
            return (x < y ? -1 : (x > y ? 1 : 0))
        }

        function compareStrings(str1, str2) {
          if ((str1 == null) || (str1 == '' ) ) str1 = ' '
          if ((str2 == null) || (str2 == '' ) ) str2 = ' '
          try {
            //str1 = str1.toString()
            //str2 = str2.toString()

            let rx = /([^\d]+|\d+)/ig
            let str1split = str1.match(rx)
            let str2split = str2.match(rx)
            for (let i = 0, l = Math.min(str1split.length, str2split.length); i < l; i++) {
              let s1 = str1split[i], s2 = str2split[i]
                if (s1 === s2) continue
                if (isNaN(+s1) || isNaN(+s2))
                    return s1 > s2 ? 1 : -1
                else
                    return +s1 - s2
            }
          }
          catch(err) {
            return 0  
          }
          return 0
        }

        let xvalue = x[this.orderField]
        let yvalue = y[this.orderField]
        if (this.orderFieldType == 'string') {
          return compareStrings(xvalue, yvalue) * (this.orderReverse == true ? -1 : 1)
        }
        else {
          return compare(xvalue, yvalue, this.orderFieldType) * (this.orderReverse == true ? -1 : 1)          
        }

      })

      return rows
    },

    paginatedRows () {
      if (typeof this.filteredRows == 'undefined') {
        return []
      }
      else {
        let paginatedRows = this.filteredRows
        if (this.perpage) {
          // if currentPagge more then pages (heppens when delete records)
          let pages = this.pages

          if ((this.currentPage > pages) && (pages > 0)) {
            this.setPage(pages)
          }
          if (this.currentPage < 1) {
            this.setPage(1)
          }
          if (typeof this.currentPage == 'undefined') {
            this.currentPage = 1
          }
          var rowStart = (this.currentPage - 1) * this.perpage
          if (rowStart >= paginatedRows.length) {
            rowStart = 0
          }
          var rowEnd = this.currentPage * this.perpage
          paginatedRows = paginatedRows.slice(rowStart, rowEnd)
        }
        return paginatedRows
      }
    },

    sum () {
      let sumlist = this.sumfields.split(' ')
      // Init Sum
      let result = {}
      for (let i=0; i<sumlist.length; i++) {
        result[sumlist[i]] = 0
      }
      // Calclate sum
      for (let row of this.rows) {
        for (let i=0; i<sumlist.length; i++) {
          if (row[sumlist[i]] != null) {
            if (!isNaN(row[sumlist[i]])) {
              result[sumlist[i]] = result[sumlist[i]] + parseFloat(row[sumlist[i]])
            }
          }
          else {
            this.$set(row, sumlist[i], 0)
          }
        }
      }
      return result
    }
  },
  
  methods: {
    order: function (field, type='string') {
      if (this.orderField === field) {
        if (this.orderReverse) {
          // disable order
          this.orderField = ''
        }
        else {
          this.orderReverse = true
        }
      }
      else {
        this.orderField = field
        this.orderFieldType = type
        this.orderReverse = false
      }
    },
    setOrder: function (field, type='string', reverse=false) {
      this.orderField = field
      this.orderFieldType = type
      this.orderReverse = reverse
    },
    unsetOrder: function () {
      this.orderField = ''
      this.orderFieldType = 'string'
      this.orderReverse = false
    },
    setPage: function (page) {
      this.currentPage = page

      if (typeof this.pagestore != 'undefined') {
        let obj = {}
        obj[this.pagestore] = page
        store.commit('tablePage', obj)
      }
    },
    setNextPage: function () {
      if (this.currentPage < this.pages) {
        this.setPage(this.currentPage + 1)
        //this.currentPage += 1
      }
    },
    setPrevPage: function () {
      if (this.currentPage > 1) {
        this.setPage(this.currentPage - 1)
        //this.currentPage -= 1
      }
    },
    setFilter: function (filter) {
      if (filter) {
        this.search = filter.search
        this.searchField = filter.field
      }
      else {
        this.search = ''
        this.searchField = ''
      }
    }
  },
  mounted: function () {
    if (typeof this.pagestore != 'undefined') {
      if (typeof store.state.tablePage[this.pagestore] != 'undefined') {
        this.setPage(store.state.tablePage[this.pagestore])
      }
    }
  }
}
