(function(exports) {

const MODEL_CODE = {
    EM_12: 11,
    EM_02: 10,
    HCR_12F: 24
}
exports.MODEL_CODE = function() { return MODEL_CODE }


exports.board_types = {
    reserved: 0,
    hdi: 1,
    di: 2,
    ai: 3,
    cti: 4,
    rtd: 5,
    vi: 6,
    ti: 19,
    ao2: 7,
    ro: 8,
    hdo: 9,
    io1: 10,
    hdi_5: 11,
    f_lcd: 13,
    f_io: 14,
    em_h: 16,
    em_l: 17,
    io3: 18,
    ao4: 20,
    hcr12f_cti: 64,
    hcr12f_hdo_di: 160,
    hcr12f_a_mb: 193,
    hcr12f_d_mb: 194,
    deleted: 255
}

let expert_page_dictionary = [
    {"minIndex" : "0x0001", "maxIndex" : "0x0FFF", "name" : "Data Type Definitions"},
    {"minIndex" : "0x1000", "maxIndex" : "0x1029", "name" : "Communication Parameters"},
    {"minIndex" : "0x1200", "maxIndex" : "0x12FF", "name" : "SDO Parameters"},
    {"minIndex" : "0x1400", "maxIndex" : "0x15FF", "name" : "Receive PDO Parameters"},
    {"minIndex" : "0x1600", "maxIndex" : "0x17FF", "name" : "Receive PDO Mapping"},
    {"minIndex" : "0x1800", "maxIndex" : "0x19FF", "name" : "Transmit PDO Parameters"},
    {"minIndex" : "0x1A00", "maxIndex" : "0x1BFF", "name" : "Transmit PDO Mapping"},
    {"minIndex" : "0x1C00", "maxIndex" : "0x1FFF", "name" : "Other Communication Parameters"},
    //{"minIndex" : "0x2000", "maxIndex" : "0x4FFF", "name" : "Manufacturer Specific"},
    {"minIndex" : "0x2000", "maxIndex" : "0x2FFF", "name" : "General Device Parameters"},
    {"minIndex" : "0x3F00", "maxIndex" : "0x3FFF", "name" : "Module 0"},
    {"minIndex" : "0x4000", "maxIndex" : "0x40FF", "name" : "Module 1"},
    {"minIndex" : "0x4100", "maxIndex" : "0x41FF", "name" : "Module 2"},
    {"minIndex" : "0x4200", "maxIndex" : "0x42FF", "name" : "Module 3"},
    {"minIndex" : "0x4300", "maxIndex" : "0x43FF", "name" : "Module 4"},
    {"minIndex" : "0x4400", "maxIndex" : "0x44FF", "name" : "Module 5"},
    {"minIndex" : "0x4500", "maxIndex" : "0x45FF", "name" : "Module 6"},
    {"minIndex" : "0x4600", "maxIndex" : "0x46FF", "name" : "Module 7"},
    {"minIndex" : "0x4700", "maxIndex" : "0x47FF", "name" : "Module 8"},
    {"minIndex" : "0x4C00", "maxIndex" : "0x4FFF", "name" : "External IO"},
    {"minIndex" : "0x3000", "maxIndex" : "0x3EFF", "name" : "Energy Profiles"},
    {"minIndex" : "0x5100", "maxIndex" : "0x53FF", "name" : "Modbus Serial 1 Client Requests"},
    {"minIndex" : "0x5400", "maxIndex" : "0x56FF", "name" : "Modbus Serial 2 Client Requests"},
    {"minIndex" : "0x5700", "maxIndex" : "0x59FF", "name" : "Modbus Serial 3 Client Requests"},
    {"minIndex" : "0x5A00", "maxIndex" : "0x5FFF", "name" : "Modbus TCP Client Requests"},
    {"minIndex" : "0x6000", "maxIndex" : "0x9FFF", "name" : "Standardized Device Profile"},
    {"minIndex" : "0x5000", "maxIndex" : "0x500F", "name" : "Application SW Parameters"},
    {"minIndex" : "0xA000", "maxIndex" : "0xAFFF", "name" : "Application SW Variables"},
    {"minIndex" : "0xB000", "maxIndex" : "0xBFFF", "name" : "Application SW Profiles"}
]
exports.expert_page_dictionary = function() { return expert_page_dictionary }



exports.add_multiply_templates = function()
{
    if (configuration.get_multiply_templates())
    {
        configuration.get_multiply_templates().forEach(function(block, i, arr) {
            //console.log(block)
            if (block.type == "index multiply")
            {
                let count = block.count
                let index_multiply = block.multiply_coefficient
                block.templates.forEach(function(item, i, arr) {
                    for (let number = 1; number <= count; number++)
                    {
                        let index_arr = item.index.split('_')
                        let index = (Number("0x" + index_arr[0]) + (number - 1)*index_multiply).toString(16).toUpperCase()
                        let sub = index_arr[1]
                        let item_clone = {};
                        Object.assign(item_clone, item)
                        item_clone.index = `${index}_${sub}`
                        configuration.add_template(item_clone)
                    }
                })
            }
            else if (block.type == "subindex multiply")
            {
                let count = block.count
                block.templates.forEach(function(item, i, arr) {
                    for (var number = 1; number <= count; number++)
                    {
                        let index = Number("0x" + item.index).toString(16).toUpperCase()
                        let item_clone = {};
                        Object.assign(item_clone, item)
                        item_clone.index = `${index}_${number}`
                        configuration.add_template(item_clone)
                    }
                })
            }
            else
            {
                console.log("illegal multi templates type")
            }
        })      
    }
    //console.log(configuration.data_type_template())
}

exports.form_tag_tr = function(param_name, eds_index, eds_subindex)
{ 
	return exports.form_tag_tr_param({name: param_name, index: eds_index, sub: eds_subindex})
}

exports.form_tag_tr_param = function(param) 
{ 
    let tr = $('<tr class="can_hide">')
    let td = $('<td>').text(param.name)
    if (param.tab)
    {
        td.addClass('name')
    }
	let div = $('<div>').attr({"index": `${param.index.toString(16).toUpperCase()}:${param.sub}`})
    if (param.simple_tag)
    {
        div.addClass("tag")
    }
    else
    {
        div.addClass("accordion_tag")
    }
    if ("type" in param)
	{
		div.addClass(param.type)
	}
    tr.append(td).append($('<td>').append(div))//.addClass("name"))
    return tr
}

exports.form_tag_tr2 = function(param_name, eds_index, eds_subindex, param_name2, eds_index2, eds_subindex2) 
{ 
	return exports.form_tag_tr2_param({name: param_name, index: eds_index, sub: eds_subindex, type: ""},
							{name: param_name2, index: eds_index2, sub: eds_subindex2, type: ""})
}

exports.form_tag_tr2_param = function(param1, param2)
{
    var tr = $('<tr class="can_hide">').append($('<td>').text(param1.name))//.addClass("name"));
	var div = $('<div>').addClass("accordion_tag").attr({"index": `${param1.index.toString(16).toUpperCase()}:${param1.sub}`});
	if ("type" in param1)
	{
		div.addClass(param1.type)
	}
    tr.append($('<td>').append(div))//.addClass("name"));
	//tr.append($('<td>'))//.addClass('empty_space'));
	if (param2.name != "")
	{
		tr.append($('<td>').text(param2.name).addClass("name"));
	}

	var div2 = $('<div>').addClass("accordion_tag").attr({"index": `${param2.index.toString(16).toUpperCase()}:${param2.sub}`});
	if ("type" in param2)
	{
		div2.addClass(param2.type)
	}
    tr.append($('<td>').append(div2))//.addClass("name"));
    return tr;
}

exports.form_tag_tr3 = function(param_name, eds_index, eds_subindex, param_name2, eds_index2, eds_subindex2, param_name3, eds_index3, eds_subindex3) 
{ 
	return exports.form_tag_tr3_param({name: param_name, index: eds_index, sub: eds_subindex, type: ""},
							{name: param_name2, index: eds_index2, sub: eds_subindex2, type: ""},
                            {name: param_name3, index: eds_index3, sub: eds_subindex3, type: ""})
}

exports.form_tag_tr3_param = function(param1, param2, param3)
{
    var tr = $('<tr class="can_hide">').append($('<td>').text(param1.name))//.addClass("name"));
	var div = $('<div>').addClass("accordion_tag").attr({"index": `${param1.index.toString(16).toUpperCase()}:${param1.sub}`});
	if ("type" in param1)
	{
		div.addClass(param1.type)
	}
    tr.append($('<td>').append(div))//.addClass("name"));
	//tr.append($('<td>'))//.addClass('empty_space'));
	if (param2.name != "")
	{
		tr.append($('<td>').text(param2.name).addClass("name"));
	}

	var div2 = $('<div>').addClass("accordion_tag").attr({"index": `${param2.index.toString(16).toUpperCase()}:${param2.sub}`});
	if ("type" in param2)
	{
		div2.addClass(param2.type)
	}
    tr.append($('<td>').append(div2))//.addClass("name"));

    var div3 = $('<div>').addClass("accordion_tag").attr({"index": `${param3.index.toString(16).toUpperCase()}:${param3.sub}`});
	if ("type" in param3)
	{
		div3.addClass(param3.type)
	}
    tr.append($('<td>').append(div3))//.addClass("name"));
    return tr;
}

exports.form_tag_divide_tr = function(param_name, eds_index_num, eds_subindex_num, eds_index_den, eds_subindex_den)
{
    var tr = $('<tr class="can_hide">').append($('<td>').text(param_name).addClass("name"));
    var table = $('<table>');
    var div1 = $('<div>').addClass("io").addClass("accordion_tag").attr({"index": `${eds_index_num.toString(16).toUpperCase()}:${eds_subindex_num}`});
    var div2 = $('<div>').addClass("io").addClass("accordion_tag").attr({"index": `${eds_index_den.toString(16).toUpperCase()}:${eds_subindex_den}`});
    table.append($('<tr>').append(($('<td style="border-bottom-color: black">').append(div1))))
    table.append($('<tr>').append(($('<td>').append(div2))))
    tr.append($('<td>').append(table));
    return tr;
}

exports.response_ready = function(response_text)
{
	return new Promise(function(resolve, reject) {
		let values = utils.get_response_values_from_text(response_text)
		resolve(values);
	})
}

})(this.common = {})

$(document).on('click', '.password_checkbox', function()
{
    if ($(this).is(':checked')){
        $('.password').attr('type', 'text')
    } else {
        $('.password').attr('type', 'password')
    }
})


$(document).on('value_loaded', 'div[tb_index="1001_0"]', function( e )
{
    let device_error = $(this).text()
    if (device_error > 0)
    {
        $('.device_status').addClass('device_error')
        $('#errors_info').show()
    }
    else
    {
        $('.device_status').removeClass('device_error')
        $('#errors_info').hide()
    }

    $(this).removeClass('value_loaded')
})

$(document).on('value_loaded', '.board_status', function( e )
{
    let board = $(this).children('form').children('div.value')
    let board_error = board.text()
    let status_index = $(this).attr('index')
    if (board_error > 0)
    {
        $(`div[status_index="${status_index}"]`).addClass('device_error')
    }
    else
    {
        $(`div[status_index="${status_index}"]`).removeClass('device_error')
    }
    $(this).removeClass('value_loaded')
})

$(document).ready(function()
{
    $.validator.addMethod("ip_addr", function(value, element)
    {
        let re = new RegExp("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$")
        //return this.optional(element) || re.test(value)
        return re.test(value)
    }, l100n.localize_string("ip_address_pass"))

    $.validator.addMethod("hex_dec_number", function(value, element)
    {
        let rule = "^((0x)[a-fA-F0-9]+)|(-?\\d+(\\.\\d{0,})?)$"
        let re = new RegExp(rule);
        //return this.optional(element) || re.test(value)
        return re.test(value)
    }, l100n.localize_string("hex_dec_number"))

    $.validator.addMethod("hex_dec_real_number", function(value, element)
    {
        let hex_dec_real_rule = "^(inf|-inf|nan|(0x)[a-fA-F0-9]+|-?\\d+(\\.\\d+)?)$"
        let re = new RegExp(hex_dec_real_rule)
        //return this.optional(element) || re.test(value)
        return re.test(value)
    }, l100n.localize_string("hex_dec_real_number"))

    $.validator.addMethod("range_localization", function(value, element, params)
    {
        return this.optional(element) || (value >= params[0] && value <= params[1])
    }, jQuery.validator.format(l100n.localize_string("range_localization") + "({0} ; {1})"))

    $.validator.addMethod("only_string", function(value, element)
    {
        let re = new RegExp("^([a-zA-Z]+)$")
        //return this.optional(element) || re.test(value)
        return re.test(value)
    }, l100n.localize_string("only_string"))

    //$.validator.addClassRules("item_edit_textbox", {messages: {required: "Введите значение."}})
    //$.validator.addClassRules("bool", {hex_dec_number: true, range: [0, 1]})
    $.validator.addClassRules("1-127", {hex_dec_number: true, range_localization: [1, 127]})
    $.validator.addClassRules("uint8", {hex_dec_number: true, range_localization: [0, 255]})
    $.validator.addClassRules("uint16", {hex_dec_number: true, range_localization: [0, 65535]})
    $.validator.addClassRules("uint32", {hex_dec_number: true, range_localization: [0, 4294967295]})
    $.validator.addClassRules("uint64", {hex_dec_number: true, range_localization: [0, 18446744073709551615]})
    $.validator.addClassRules("int8", {hex_dec_number: true, range_localization: [-128, 127]})
    $.validator.addClassRules("int16", {hex_dec_number: true, range_localization: [-32768, 32767]})
    $.validator.addClassRules("int32", {hex_dec_number: true, range_localization: [-2147483648, 2147483647]})
    $.validator.addClassRules("int64", {hex_dec_number: true, range_localization: [-9223372036854775808, 9223372036854775807]})
    $.validator.addClassRules("real32", {hex_dec_real_number: true})
    $.validator.addClassRules("mbtcp_client_timeout", {hex_dec_number: true, range_localization: [10, 1023]})
    $.validator.addClassRules("percent", {hex_dec_real_number: true, range_localization: [0, 100]})
    $.validator.addClassRules("string_command", {only_string: true})
})


