//~ Empresa Libre
//~ Copyright (C) 2016-2018  Mauricio Baeza Servin (web@correolibre.net)
//~
//~ This program is free software: you can redistribute it and/or modify
//~ it under the terms of the GNU General Public License as published by
//~ the Free Software Foundation, either version 3 of the License, or
//~ (at your option) any later version.
//~
//~ This program is distributed in the hope that it will be useful,
//~ but WITHOUT ANY WARRANTY; without even the implied warranty of
//~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//~ GNU General Public License for more details.
//~
//~ You should have received a copy of the GNU General Public License
//~ along with this program.  If not, see <http://www.gnu.org/licenses/>.


var PUBLICO = "PUBLICO EN GENERAL";
var RFC_PUBLICO = "XAXX010101000";
var RFC_EXTRANJERO = "XEXX010101000";
var PAIS = "México";
var DECIMALES = 2;
//~ var DECIMALES_PU = 4;
var DECIMALES_TAX = 4;
var CLAVE_ANTICIPOS = '84111506';
var CURRENCY_MN = 'MXN';
var KEY_SAT_01 = '01010101';


var db = new loki('data.db');
var table_config = db.addCollection('config')
var table_taxes = db.addCollection('taxes')
var table_pt = db.addCollection('productstaxes')
var table_totals = db.addCollection('totals', {unique: ['tax']})
var table_series = db.addCollection('series')
var table_usocfdi = db.addCollection('usocfdi')
var table_relaciones = db.addCollection('relaciones')
var table_waypayment = db.addCollection('waypayment')

var msg = ''

var months = [
    {id: -1, value: 'Todos'},
    {id: 1, value: 'Enero'},
    {id: 2, value: 'Febrero'},
    {id: 3, value: 'Marzo'},
    {id: 4, value: 'Abril'},
    {id: 5, value: 'Mayo'},
    {id: 6, value: 'Junio'},
    {id: 7, value: 'Julio'},
    {id: 8, value: 'Agosto'},
    {id: 9, value: 'Septiembre'},
    {id: 10, value: 'Octubre'},
    {id: 11, value: 'Noviembre'},
    {id: 12, value: 'Diciembre'},
]

var days = [
    {id: -1, value: '00'},
    {id: 1, value: '01'},
    {id: 2, value: '02'},
    {id: 3, value: '03'},
    {id: 4, value: '04'},
    {id: 5, value: '05'},
    {id: 6, value: '06'},
    {id: 7, value: '07'},
    {id: 8, value: '08'},
    {id: 9, value: '09'},
    {id: 10, value: '10'},
    {id: 11, value: '11'},
    {id: 12, value: '12'},
    {id: 13, value: '13'},
    {id: 14, value: '14'},
    {id: 15, value: '15'},
    {id: 16, value: '16'},
    {id: 17, value: '17'},
    {id: 18, value: '18'},
    {id: 19, value: '19'},
    {id: 20, value: '20'},
    {id: 21, value: '21'},
    {id: 22, value: '22'},
    {id: 23, value: '23'},
    {id: 24, value: '24'},
    {id: 25, value: '25'},
    {id: 26, value: '26'},
    {id: 27, value: '27'},
    {id: 28, value: '28'},
    {id: 29, value: '29'},
    {id: 30, value: '30'},
    {id: 31, value: '31'},
]



function get_icon(tipo){
    icons = {
        xml: 'fa-file-code-o',
        pdf: 'fa-file-pdf-o',
        html: 'fa-html5',
        zip: 'fa-file-zip-o',
        email: 'fa-envelope-o',
        print: 'fa-print',
        table: 'fa-table',
    }
    return "<span class='webix_icon " + icons[tipo] + "'></span>"
}


function focus(name){
    webix.UIManager.setFocus(name)
}


function select_all(name){
    focus(name)
    $$(name).getInputNode().select()
}


function to_end(name){
    focus(name)
    var txt = $$(name)
    var pos = txt.getValue().length
    var height = txt.getInputNode().scrollHeight

    webix.html.setSelectionRange(txt.getInputNode(), pos)
    txt.getInputNode().scrollTop = height
}


function showvar(values){
    webix.message(JSON.stringify(values, null, 2))
}


function showtype(values){
    webix.message(typeof(values))
}


function show(nombre, value){
    if(value == '0'){
        value = false
    }
    if(value){
        $$(nombre).show()
    }else{
        $$(nombre).hide()
    }
}


function show_column(table, column){
    $$(table).showColumn(column)
}


function enable(nombre, value){
    if(value == '0'){
        value = false
    }
    if(value){
        $$(nombre).enable()
    }else{
        $$(nombre).disable()
    }
}


function msg_error(msg){
    if(!msg){
        msg = 'Error al consultar'
    }
    webix.message({type: 'error', text: msg})
}


function msg_ok(msg){
    webix.message({type: 'success', text: msg})
}


Number.prototype.round = function(decimals){
    return Number((Math.round(this + "e" + decimals)  + "e-" + decimals))
}


String.prototype.is_number = function(){
    return /^\d+$/.test(this)
}
String.prototype.to_float = function(){
    return get_float(this)
}
String.prototype.to_float4 = function(){
    return get_float4(this)
}


function get_float(value){
    var f = parseFloat(value.replace('$', '').replace(/,/g, '').trim()).round(DECIMALES)
    if(!f){
        f = 0.00
    }
    return f
}


function get_float4(value){
    var f = parseFloat(value.replace('$', '').replace(/,/g, '').trim()).round(DECIMALES_TAX)
    if(!f){
        f = 0.00
    }
    return f
}


var format_decimal_2 = webix.Number.numToStr({
  groupSize: 3,
  decimalSize: 2,
  groupDelimiter: ",",
  decimalDelimiter: "."
})

var format_decimal_4 = webix.Number.numToStr({
  groupSize: 3,
  decimalSize: 4,
  groupDelimiter: ",",
  decimalDelimiter: "."
})


function format_currency(value){
    var fv = ''
    if(get_config('decimales_precios') == 4){
        fv = '$ ' + format_decimal_4(value)
    }else{
        fv = '$ ' + format_decimal_2(value)
    }
    return fv
}


function format_currency2(value){
    return '$ ' + format_decimal_2(value)
}


function format_currency4(value){
    return '$ ' + format_decimal_4(value)
}


webix.protoUI({
    $cssName: "text",
    name: "currency",
    $init:function(){
        this.attachEvent("onItemClick", function(){
            this.$setValue(this.config.raw, true)
            this.getInputNode().select()
        })
        this.attachEvent("onBlur", function(){
            this.$setValue(this.config.value)
        })
    },
    $render:function(){
        this.$setValue(this.config.value)
    },
    $setValue:function(value, raw){
        this.config.raw = value
        if(!raw){
            value = format_currency(value)
        }
        this.getInputNode().value = value
    }
}, webix.ui.text)


webix.protoUI({
    $cssName: "text",
    name: "currency4",
    $init:function(){
        this.attachEvent("onItemClick", function(){
            this.$setValue(this.config.raw, true)
            this.getInputNode().select()
        })
        this.attachEvent("onBlur", function(){
            this.$setValue(this.config.value)
        })
    },
    $render:function(){
        this.$setValue(this.config.value)
    },
    $setValue:function(value, raw){
        this.config.raw = value
        if(!raw){
            value = format_currency4(value)
        }
        this.getInputNode().value = value
    }
}, webix.ui.text)


webix.protoUI({
    $cssName: "text",
    name: "currency2",
    $init:function(){
        this.attachEvent("onItemClick", function(){
            this.$setValue(this.config.raw, true)
            this.getInputNode().select()
        })
        this.attachEvent("onBlur", function(){
            this.$setValue(this.config.value)
        })
    },
    $render:function(){
        this.$setValue(this.config.value)
    },
    $setValue:function(value, raw){
        this.config.raw = value
        if(!raw){
            value = format_currency2(value)
        }
        this.getInputNode().value = value
    }
}, webix.ui.text)


webix.ui.datafilter.countRows = webix.extend({
    refresh:function(master, node, value){
        node.firstChild.innerHTML = master.count();
    }
}, webix.ui.datafilter.summColumn);


webix.ui.datafilter.summActive = webix.extend({
    refresh:function(master, node, value){
        node.firstChild.innerHTML = this.summGenerate(master);
    },
    summGenerate:function(master){
        var sum = 0
        master.eachRow(function(id){
            var row = master.getItem(id)
            if(row.estatus == 'Generado'){
                var importe = row.total
                if(typeof importe === 'string'){
                    importe = row.total.to_float()
                }
                sum += importe
            }
        })
     return webix.i18n.priceFormat(sum)
   }
}, webix.ui.datafilter.summColumn);


webix.ui.datafilter.summTimbrada = webix.extend({
    refresh:function(master, node, value){
        node.firstChild.innerHTML = this.summGenerate(master);
    },
    summGenerate:function(master){
        var sum = 0
        master.eachRow(function(id){
            var row = master.getItem(id)
            if(row.estatus == 'Timbrada'){
                var importe = row.total_mn
                if(typeof importe === 'string'){
                    importe = row.total_mn.to_float()
                }
                sum += importe
            }
        })
     return webix.i18n.priceFormat(sum)
   }
}, webix.ui.datafilter.summColumn);


webix.ui.datafilter.summTimbradaN = webix.extend({
    refresh:function(master, node, value){
        node.firstChild.innerHTML = this.summGenerate(master);
    },
    summGenerate:function(master){
        var sum = 0
        master.eachRow(function(id){
            var row = master.getItem(id)
            if(row.estatus == 'Timbrado'){
                var importe = row.total
                if(typeof importe === 'string'){
                    importe = row.total.to_float()
                }
                sum += importe
            }
        })
        return webix.i18n.priceFormat(sum)
   }
}, webix.ui.datafilter.summColumn);



function validate_rfc(value){
    rfc = value.trim().toUpperCase();
    if ( rfc == ""){
        msg_error('El RFC no puede estar vacío')
        return false
    }

    var tipo_persona = $$('tipo_persona').getValue()
    var length = 13
    var start = 4
    if(tipo_persona==2){
        length = 12
        start = 2
    }
    if (rfc.length != length){
        msg_error('Longitud incorrecta del RFC')
        return false
    }
    if (tipo_persona < 3 && (rfc == RFC_PUBLICO || rfc == RFC_EXTRANJERO)){
        msg_error('RFC incorrecto')
        return false
    }

    var part = rfc.slice(0, start);
    var re = new RegExp('[a-z&Ñ]{' + start + '}', 'i');
    if (!part.match(re)){
        msg_error('El RFC tiene caractéres inválidos al inicio')
        return false
    }
    part = rfc.slice(-3);
    re = new RegExp('[a-z0-9]{3}', 'i');
    if (!part.match(re)){
        msg_error('El RFC tiene caractéres inválidos al final')
        return false
    }

    part = rfc.slice(-9, -3);
    re = new RegExp('[0-9]{6}', 'i');
    if (!part.match(re)){
        msg_error('Fecha inválida')
        return false
    }
    var month = parseInt(part.slice(-4, -2))
    if (month == 0 || month > 12 ){
        msg_error('Fecha inválida')
        return false
    }
    var day = parseInt(part.slice(-2))
    if (day == 0 || day > 31 ){
        msg_error('Fecha inválida')
        return false
    }

    return true
}


function validar_rfc(value){
    rfc = value.trim().toUpperCase();
    if (rfc == ""){
        msg_error('El RFC no puede estar vacío')
        return false
    }

    if (rfc.length < 12 || rfc.length > 13){
        msg_error('Longitud incorrecta del RFC')
        return false
    }

    var length = rfc.length
    var start = 4
    if(length==12){
        start = 2
    }

    var part = rfc.slice(0, start);
    var re = new RegExp('[a-z&Ñ]{' + start + '}', 'i');
    if (!part.match(re)){
        msg_error('El RFC tiene caractéres inválidos al inicio')
        return false
    }
    part = rfc.slice(-3);
    re = new RegExp('[a-z0-9]{3}', 'i');
    if (!part.match(re)){
        msg_error('El RFC tiene caractéres inválidos al final')
        return false
    }

    part = rfc.slice(-9, -3);
    re = new RegExp('[0-9]{6}', 'i');
    if (!part.match(re)){
        msg_error('Fecha inválida')
        return false
    }
    var month = parseInt(part.slice(-4, -2))
    if (month == 0 || month > 12 ){
        msg_error('Fecha inválida')
        return false
    }
    var day = parseInt(part.slice(-2))
    if (day == 0 || day > 31 ){
        msg_error('Fecha inválida')
        return false
    }

    return true
}


function validate_email(email){
    var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
    return re.test(email)
}


function add_config(args){
    var key = table_config.findOne({key: args.key})
    if(key===null){
        table_config.insert(args)
    }else{
        key.value = args.value
        table_config.update(key)
    }
}


function get_config(value){
    var key = table_config.findOne({key: value})
    if(key===null){
        return ''
    }else{
        return key.value
    }
}


webix.DataDriver.plainjs = webix.extend({
  arr2hash:function(data){
    var hash = {};
    for (var i=0; i<data.length; i++){
      var pid = data[i].parent_id;
      if (!hash[pid]) hash[pid]=[];
      hash[pid].push(data[i]);
    }
    return hash;
  },
  hash2tree:function(hash, level){
    var top = hash[level];
    for (var i=0; i<top.length; i++){
      var branch = top[i].id;
      if (hash[branch])
        top[i].data = this.hash2tree(hash, branch);
    }
    return top;
  },
  getRecords:function(data, id){
    var hash = this.arr2hash(data);
    return this.hash2tree(hash, 0);
  }
}, webix.DataDriver.json)


function get_forma_pago(control){
    webix.ajax().get('/values/formapago', {key: true}, function(text, data){
        var values = data.json()
        $$(control).getList().parse(values)
    })
}


function get_way_payment(){
    webix.ajax().get('/satformapago', {opt: 'active_by_id'}, function(text, data){
        var values = data.json()
        table_waypayment.clear()
        table_waypayment.insert(values)
    })
}


function set_way_payment(control, filter99=false, current_way_payment=''){
    if(filter99){
        var values = table_waypayment.chain().find({'value': { '$ne' : 'Por definir' }}).data()
    }else{
        var values = table_waypayment.chain().data()
    }
    $$(control).getList().parse(values)
    if(current_way_payment){
        $$(control).setValue(current_way_payment)
    }
}


function validate_regexp(value, pattern){
    re = new RegExp(pattern, 'i');
    if(value.match(re)){
        return true
    }else{
        return false
    }
}


function validate_pedimento(value){
    var pattern = '[0-9]{2}  [0-9]{2}  [0-9]{4}  [0-9]{7}'
    return validate_regexp(value, pattern)
}


function validate_curp(value){
    var pattern = '[A-Z][A,E,I,O,U,X][A-Z]{2}[0-9]{2}[0-1][0-9][0-3][0-9][M,H][A-Z]{2}[B,C,D,F,G,H,J,K,L,M,N,Ñ,P,Q,R,S,T,V,W,X,Y,Z]{3}[0-9,A-Z][0-9]'
    return validate_regexp(value, pattern)
}


//config may as well include only text, color and date hash
webix.editors.$popup = {
    text:{
        view: 'popup', width:500, height:200,
        body: {view: 'textarea'}
    },
};


function pause(milliseconds) {
    var dt = new Date();
    while ((new Date()) - dt <= milliseconds) { /* Do nothing */ }
}



//~ Revisado

function lst_clear(lst){
    lst.setValue('')
    lst.define('options', [])
    lst.refresh()
}


function lst_parse(lst, values){
    lst.getList().parse(values)
}


function lst_parse2(lst_name, values){
    obj = $$(lst_name)
    obj.getList().parse(values)
}


function set_value(control, value){
    obj = $$(control)
    obj.blockEvent()
    obj.setValue(value)
    obj.unblockEvent()
}


function grid_parse(grid_name, values){
    obj = $$(grid_name)
    obj.clearAll()
    obj.parse(values)
}


function activate_tab(parent, name){
    $$(parent).getTabbar().setValue(name)
}


var opt_global_periodicidad = [
    {id: '01', value: '[01] Diario'},
    {id: '02', value: '[02] Semanal'},
    {id: '03', value: '[03] Quincenal'},
    {id: '04', value: '[04] Mensual'},
    {id: '05', value: '[05] Bimestral'},
]

var opt_global_months = [
    {id: '01', value: '[01] Enero'},
    {id: '02', value: '[02] Febrero'},
    {id: '03', value: '[03] Marzo'},
    {id: '04', value: '[04] Abril'},
    {id: '05', value: '[05] Mayo'},
    {id: '06', value: '[06] Junio'},
    {id: '07', value: '[07] Julio'},
    {id: '08', value: '[08] Agosto'},
    {id: '09', value: '[09] Septiembre'},
    {id: '10', value: '[10] Octubre'},
    {id: '11', value: '[11] Noviembre'},
    {id: '12', value: '[12] Diciembre'},
    {id: '13', value: '[13] Enero-Febrero'},
    {id: '14', value: '[14] Marzo-Abril'},
    {id: '15', value: '[15] Mayo-Junio'},
    {id: '16', value: '[16] Julio-Agosto'},
    {id: '17', value: '[17] Septiembre-Octubre'},
    {id: '18', value: '[18] Noviembre-Diciembre'},
]
