<commit_before><html>
<head>
<link rel="stylesheet" type="text/css" href="../../lib/css/themes/jquery-ui/redmond/jquery-ui.min.css"/>
<link rel="stylesheet" type="text/css" href="../../lib/css/fancytree/ui.fancytree.min.css"/>

<script type="text/javascript" src="../../lib/js/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="../../socket.io/socket.io.js"></script>
<script type="text/javascript" src="../../lib/js/jquery-ui-1.10.3.full.min.js"></script>

<link rel="stylesheet" type="text/css" href="../../css/adapter.css"/>
<script type="text/javascript" src="../../lib/js/translate.js"></script>
<script type="text/javascript" src="../../js/adapter-settings.js"></script>
<script type="text/javascript" src="../../lib/js/jquery.fancytree-all.min.js"></script>
<script type="text/javascript" src="../../lib/js/selectID.js"></script>
<script type="text/javascript" src="words.js"></script>

<script type="text/javascript">

    var supportedInstances = ['web'];
    var subscribed = false;
    var subscribed3 = false;
    var actionsMapping = {
        turnOn: 'On',
        turnOff: 'Off',
        setTargetTemperature: '°',
        incrementTargetTemperature: '↑',
        decrementTargetTemperature: '↓',
        setPercentage: '%',
        incrementPercentage: '↑',
        decrementPercentage: '↓',
        setColor: 'hsb',
        incrementColorTemperature: '☀↑',
        decrementColorTemperature: '☀↓',
        setColorTemperature: '☀',
        getTargetTemperature: '±?',
        getTemperatureReading: '°?',
        setLockState: '🔒',
        getLockState: '🔒?'
    };
    var enumTimer;
    var devTimer;
    var devMTimer;
    var selectId;
    var filterTimer;
    var filterMTimer;
    var idToEdit;
    var idToNavigate;
    var language;
    var noCommon;

    function getSmartName(states, id) {
        if (!id) {
            if (!noCommon) {
                if (!states.common) {
                    return states.smartName;
                } else {
                    if (states && !states.common) {
                        return states.smartName;
                    } else {
                        return states.common.smartName;
                    }
                }
            } else {
                if (states && !states.common) {
                    return states.smartName;
                } else {
                    return (states &&
                        states.common &&
                        states.common.custom &&
                        states.common.custom[adapter + '.' + instance]) ?
                        states.common.custom[adapter + '.' + instance].smartName : undefined;
                }
            }
        } else
        if (!noCommon) {
            return states[id].common.smartName;
        } else {
            return (states[id] &&
                states[id].common &&
                states[id].common.custom &&
                states[id].common.custom[adapter + '.' + instance]) ?
                states[id].common.custom[adapter + '.' + instance].smartName || null : null;
        }
    }

    function initSelectId(callback) {
        if (selectId) {
            return callback(selectId);
        }
        socket.emit('getObjects', function (err, objs) {
            selectId = $('#dialog-select-member').selectId('init',  {
                noMultiselect: true,
                objects: objs,
                imgPath:       '../../lib/css/fancytree/',
                filter:        {type: 'state'},
                name:          'scenes-select-state',
                texts: {
                    select:          _('Select'),
                    cancel:          _('Cancel'),
                    all:             _('All'),
                    id:              _('ID'),
                    name:            _('Name'),
                    role:            _('Role'),
                    room:            _('Room'),
                    value:           _('Value'),
                    selectid:        _('Select ID'),
                    from:            _('From'),
                    lc:              _('Last changed'),
                    ts:              _('Time stamp'),
                    wait:            _('Processing...'),
                    ack:             _('Acknowledged'),
                    selectAll:       _('Select all'),
                    unselectAll:     _('Deselect all'),
                    invertSelection: _('Invert selection')
                },
                columns: ['image', 'name', 'role', 'room']
            });
            callback(selectId);
        });
    }

    function initDialog() {
        var $editDialog = $('#edit_dialog');
        if (!$editDialog.data('inited')) {
            $editDialog.data('inited', true);
            $editDialog.dialog({
                autoOpen: false,
                title:    _('Edit smart name'),
                modal:    true,
                width:    600,
                height:   230,
                buttons: [
                    {
                        id:    'edit-ok',
                        text: _('Ok'),
                        click: function () {
                            $(this).dialog('close');
                            var callback = $('#edit_dialog').data('callback');
                            if (typeof callback === 'function') callback();
                        }
                    },
                    {
                        text: _('Cancel'),
                        click: function () {
                            $(this).dialog('close');
                        }
                    }
                ]
            });
            $('#edit_name').keyup(function (e) {
                if (e.keyCode === 13) {
                    setTimeout(function () {
                        $('#edit-ok').trigger('click');
                    }, 100);
                }
            });
        }
    }

    function getSelect(id, type) {
        // type = '-', false or number [5-100]
        if (type !== false) {
            var text = '<select data-id="' + id + '" class="by-on-edit">';
            text += '<option value="-" ' + (type === '-' ? 'selected' : '') + '>' + _('last value') + '</option>';
            for (var i = 5; i <= 100; i += 5) {
                text += '<option value="' + i + '" ' + (type === i.toString() ? 'selected' : '') + '>' + i + '%</option>';
            }
            text += '</select>';
            return text;
        } else {
            return '';
        }
    }

    const SMARTTYPES = ["LIGHT", "SWITCH", "THERMOSTAT", "ACTIVITY_TRIGGER","SCENE_TRIGGER","SMARTPLUG","SMARTLOCK","CAMERA"]

    function getTypeSelect(id, type) {
        // type = '-', false or number [5-100]
        if (type !== false) {
            var text = '<select data-id="' + id + '" class="type-edit">';
            text += '<option value="" ' + ((!type) ? 'selected' : '') + '>' + _('no type') + '</option>';
            for(var i=0; i<SMARTTYPES.length; i++) {
                text += '<option value="' + SMARTTYPES[i] + '" ' + (type === SMARTTYPES[i] ? 'selected' : '') + '>' + SMARTTYPES[i] + '</option>';
            }
            text += '</select>';
            return text;
        } else {
            return '';
        }
    }

    function updateDevices(delay) {
        if (delay) {
            if (devTimer) clearTimeout(devTimer);
            devTimer = setTimeout(function () {
                devTimer = null;
                updateDevices();
            }, delay);
            return;
        }
        sendTo(null, 'browse', null, function (list) {
            if (list) {
                var text = '<tr><th style="width: 30%">' + _('Smart name') + '</th><th style="width: 100px">' + _('Commands') + '</th><th style="width: 70%">' + _('Addresses') + '<span style="float: right; padding-right: 130px">' + _('Types') + '</span><span style="float: right; padding-right: 130px">' + _('by ON') + '</span></th></tr>';

                for (var j = 0; j < list.length; j++) {
                    if (list[j].additionalApplianceDetails.group || !list[j].additionalApplianceDetails.nameModified) {
                        text += '<tr><td class="smart-name"  style="white-space: nowrap;">' + list[j].friendlyName + '</td>';
                    } else {
                        text += '<tr><td class="smart-name"  style="white-space: nowrap; font-style: italic" title="' + _('modified') + '">' + list[j].friendlyName + '</td>';
                    }
                    // Type
                    var actions = [];
					if (!list[j].actions) {
						console.log('Something went wrong');
						continue;
					}
					for (var a = 0; a < list[j].actions.length; a++) {
                        if (actionsMapping[list[j].actions[a]]) {
                            actions.push(actionsMapping[list[j].actions[a]]);
                        } else {
                            actions.push(list[j].actions[a]);
                        }
                    }
                    // place ON /OFF first
                    var pos = actions.indexOf(actionsMapping.turnOff);
                    if (pos !== -1) {
                        actions.splice(pos, 1);
                        actions.unshift(actionsMapping.turnOff)
                    }
                    pos = actions.indexOf(actionsMapping.turnOn);
                    if (pos !== -1) {
                        actions.splice(pos, 1);
                        actions.unshift(actionsMapping.turnOn)
                    }

                    text += '<td style="white-space: nowrap;">' + actions.join(' ') + '</td>';

                    text += '<td>';
                    text += '<table style="width: 100%" class="smart-table">';
                    
                    if (list[j].additionalApplianceDetails.group) {
                        var channels = list[j].additionalApplianceDetails.channels;
                        var names = list[j].additionalApplianceDetails.names;
                        var types = list[j].additionalApplianceDetails.byONs;
                        var smarttypes = list[j].additionalApplianceDetails.smartTypes;

                        for (var chan in channels) {
                            for (var i=0; i<channels[chan].length; i++) {
                                var k = chan+"."+channels[chan][i].split(' ')[0];
                                text += '<tr><td title="' + k + '">' + (names[k] || k) + '</td>';
                                text += '<td style="width: 95px">' + getSelect(k, types[k]) + '</td>';
                                text += '<td style="width: 95px">' + getTypeSelect(k, smarttypes[k]) + '</td>';
                                text += '<td style="width: 95px"><button data-id="' + k + '" class="button-delete"></button></td></tr>';
                            }
                        }
                    } else {
                        var name = list[j].additionalApplianceDetails.name;
                        text += '<tr><td title="' + (list[j].additionalApplianceDetails.id || '') + '">';
                        text +=  name;
                        text += '</td>';
                        text += '<td style="width: 95px">' + getSelect(list[j].additionalApplianceDetails.id, list[j].additionalApplianceDetails.byON) + '</td>';
                        text += '<td style="width: 95px">' + getTypeSelect(list[j].additionalApplianceDetails.id, list[j].additionalApplianceDetails.smartType) + '</td>';
                        text += '<td style="width: 95px"><button data-id="' + list[j].additionalApplianceDetails.id + '" class="button-delete"></button><button data-value="' + (list[j].additionalApplianceDetails.friendlyNames ? list[j].additionalApplianceDetails.friendlyNames : list[j].friendlyName) + '" data-id="' + list[j].additionalApplianceDetails.id + '" class="button-edit"></button></td>';
                        text += '</td></tr>';
                    }
                    text += '</table>';
                    text += '</td></tr>';
                }

                var $smartTable = $('#smart_table');
                $smartTable.html(text).find('.button-delete').click(function () {
                    var $this = $(this);
                    var id = $this.data('id');

                    confirmMessage(_('Device will be disabled.'), _('Are you sure?'), 'alert', function (result) {
                        if (result) {
                            $this.parent().addClass('smart-changed');
                            socket.emit('getObject', id, function (err, obj) {
                                disableSmartName(obj);
                                socket.emit('setObject', id, obj, function (err) {
                                    //updateDevices(2000);
                                    if (err) {
                                        window.alert(err);
                                    }
                                });
                            });
                        }
                    });
                }).button({icons: {primary: 'ui-icon-trash'}, text: false}).css({width: '26px', height: '26px'});

                $smartTable.find('.by-on-edit').change(function () {
                    var $this = $(this);
                    var id    = $this.data('id');
                    var val   = $this.val();
                    $this.addClass('smart-changed');
                    socket.emit('getObject', id, function (err, obj) {
                        updateSmartName(obj, null, undefined, val);
                        socket.emit('setObject', id, obj, function (err) {
                            //updateDevices(2000);
                            if (err) {
                                window.alert(err);
                            }
                        });
                    });
                });
                
                $smartTable.find('.type-edit').change(function () {
                    var $this = $(this);
                    var id    = $this.data('id');
                    var val   = $this.val();
                    $this.addClass('smart-changed');
                    socket.emit('getObject', id, function (err, obj) {
                        updateSmartName(obj, null, undefined, undefined, val);
                        socket.emit('setObject', id, obj, function (err) {
                            //updateDevices(2000);
                            if (err) {
                                window.alert(err);
                            }
                        });
                    });
                });

                $smartTable.find('.button-edit').click(function () {
                    var $this = $(this);
                    var $editDialog = $('#edit_dialog');
                    $editDialog.data('id', $this.data('id'));
                    $('#edit_name').val($this.data('value'));

                    initDialog();

                    $editDialog.data('callback', function () {
                        var id = $('#edit_dialog').data('id');

                        var $devices = $('#smart_table').find('.button-edit');

                        var val   = $('#edit_name').val();
                        var found = false;
                        $devices.each(function () {
                            if ($(this).data('value') === val && $(this).data('id') !== id) {
                                found = true;
                                return false;
                            }
                        });

                        if (found) {
                            showMessage(_('Duplicate name'), _('Error'), 'alert');
                            return;
                        }

                        //noinspection JSJQueryEfficiency
                        $devices.find('[data-id="' + id + '"]').parent().addClass('smart-changed');

                        idToNavigate = id;
                        socket.emit('getObject', id, function (err, obj) {
                            updateSmartName(obj, null, $('#edit_name').val());
                            socket.emit('setObject', id, obj, function (err) {
                                //updateDevices(2000);
                                if (err) {
                                    window.alert(err);
                                }
                            });
                        });
                    });
                    $editDialog.dialog('open');
                }).button({icons: {primary: 'ui-icon-pencil'}, text: false}).css({width: '26px', height: '26px'});

                if (idToEdit) {
                    $smartTable.find('.button-edit[data-id="' + idToEdit + '"]').trigger('click');
                    idToEdit = null;
                }
                if (idToNavigate) {
                    var $td = $smartTable.find('.button-edit[data-id="' + idToNavigate + '"]');
                    $td[0].scrollIntoView();
                    $td.parent().parent().addClass('highlight');
                    idToNavigate = null;
                }
            }
            filter();
        });
    }

    function disableSmartName(states, id) {
        var obj;
        if (!id) {
            obj = states;
        } else {
            obj = states[id];
        }
        if (noCommon) {
            obj.common.custom = obj.common.custom || {};
            obj.common.custom[adapter + '.' + instance] = obj.common.custom[adapter + '.' + instance] || {};
            obj.common.custom[adapter + '.' + instance].smartName = false;
        } else {
            obj.common.smartName = false;
        }
    }

    function enableSmartName(states, id) {
        var obj;
        if (!id) {
            obj = states;
        } else {
            obj = states[id];
        }
        if (noCommon) {
            obj.common.custom = obj.common.custom || {};
            obj.common.custom[adapter + '.' + instance] = obj.common.custom[adapter + '.' + instance] || {};
            obj.common.custom[adapter + '.' + instance].smartName = {};
        } else {
            obj.common.smartName = {};
        }
    }

    function removeSmartName(states, id) {
        var obj;
        if (!id) {
            obj = states;
        } else {
            obj = states[id];
        }
        if (noCommon) {
            if (obj.common && obj.common.custom && obj.common.custom[adapter + '.' + instance]) {
                delete obj.common.custom[adapter + '.' + instance];
            }
        } else {
            obj.common.smartName = null;
        }
    }

    function updateSmartName(states, id, newSmartName, byON, smartType) {
        var obj;
        if (!id) {
            obj = states;
        } else {
            obj = states[id];
        }

        // convert Old format
        if (typeof obj.common.smartName === 'string') {
            var nnn = obj.common.smartName;
            obj.common.smartName = {};
            obj.common.smartName[language] = nnn;
        }

        // convert old settings
        if (obj.native && obj.native.byON) {
            delete obj.native.byON;
            var _smartName = obj.common.smartName;

            if (!_smartName || typeof _smartName !== 'object') {
                _smartName = {
                    en:     _smartName
                };
                _smartName[language] = _smartName.en;
            }
            obj.common.smartName = _smartName;
        }
        if (smartType !== undefined) {
            if (noCommon) {
                obj.common.custom = obj.common.custom || {};
                obj.common.custom[adapter + '.' + instance] = obj.common.custom[adapter + '.' + instance] || {};
                obj.common.custom[adapter + '.' + instance].smartName = obj.common.custom[adapter + '.' + instance].smartName || {};
                obj.common.custom[adapter + '.' + instance].smartName.smartType = smartType;
            } else {
                obj.common.smartName = obj.common.smartName || {};
                obj.common.smartName.smartType = smartType;
            }
        }
        if (byON !== undefined) {
            if (noCommon) {
                obj.common.custom = obj.common.custom || {};
                obj.common.custom[adapter + '.' + instance] = obj.common.custom[adapter + '.' + instance] || {};
                obj.common.custom[adapter + '.' + instance].smartName = obj.common.custom[adapter + '.' + instance].smartName || {};
                obj.common.custom[adapter + '.' + instance].smartName.byON = byON;
            } else {
                obj.common.smartName = obj.common.smartName || {};
                obj.common.smartName.byON = byON;
            }
        }
        if (newSmartName !== undefined) {
            var smartName;
            if (noCommon) {
                obj.common.custom = obj.common.custom || {};
                obj.common.custom[adapter + '.' + instance] = obj.common.custom[adapter + '.' + instance] || {};
                obj.common.custom[adapter + '.' + instance].smartName = obj.common.custom[adapter + '.' + instance].smartName || {};
                smartName = obj.common.custom[adapter + '.' + instance].smartName;
            } else {
                obj.common.smartName = obj.common.smartName || {};
                smartName = obj.common.smartName;
            }
            smartName[language] = newSmartName;

            if (smartName && (!smartName[language] || (smartName[language] === obj.common.name && (!obj.common.role || obj.common.role.indexOf('button') === -1)))) {
                delete smartName[language];
                var empty = true;
                for (var key in smartName) {
                    if (smartName.hasOwnProperty(key)) {
                        empty = false;
                        break;
                    }
                }
                if (empty) {
                    if (noCommon) {
                        if (obj.common.custom[adapter + '.' + instance].smartName.byON === undefined) {
                            delete obj.common.custom[adapter + '.' + instance];
                        } else {<commit_msg>correct 'button' check<commit_after><html>
<head>
<link rel="stylesheet" type="text/css" href="../../lib/css/themes/jquery-ui/redmond/jquery-ui.min.css"/>
<link rel="stylesheet" type="text/css" href="../../lib/css/fancytree/ui.fancytree.min.css"/>

<script type="text/javascript" src="../../lib/js/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="../../socket.io/socket.io.js"></script>
<script type="text/javascript" src="../../lib/js/jquery-ui-1.10.3.full.min.js"></script>

<link rel="stylesheet" type="text/css" href="../../css/adapter.css"/>
<script type="text/javascript" src="../../lib/js/translate.js"></script>
<script type="text/javascript" src="../../js/adapter-settings.js"></script>
<script type="text/javascript" src="../../lib/js/jquery.fancytree-all.min.js"></script>
<script type="text/javascript" src="../../lib/js/selectID.js"></script>
<script type="text/javascript" src="words.js"></script>

<script type="text/javascript">

    var supportedInstances = ['web'];
    var subscribed = false;
    var subscribed3 = false;
    var actionsMapping = {
        turnOn: 'On',
        turnOff: 'Off',
        setTargetTemperature: '°',
        incrementTargetTemperature: '↑',
        decrementTargetTemperature: '↓',
        setPercentage: '%',
        incrementPercentage: '↑',
        decrementPercentage: '↓',
        setColor: 'hsb',
        incrementColorTemperature: '☀↑',
        decrementColorTemperature: '☀↓',
        setColorTemperature: '☀',
        getTargetTemperature: '±?',
        getTemperatureReading: '°?',
        setLockState: '🔒',
        getLockState: '🔒?'
    };
    var enumTimer;
    var devTimer;
    var devMTimer;
    var selectId;
    var filterTimer;
    var filterMTimer;
    var idToEdit;
    var idToNavigate;
    var language;
    var noCommon;

    function getSmartName(states, id) {
        if (!id) {
            if (!noCommon) {
                if (!states.common) {
                    return states.smartName;
                } else {
                    if (states && !states.common) {
                        return states.smartName;
                    } else {
                        return states.common.smartName;
                    }
                }
            } else {
                if (states && !states.common) {
                    return states.smartName;
                } else {
                    return (states &&
                        states.common &&
                        states.common.custom &&
                        states.common.custom[adapter + '.' + instance]) ?
                        states.common.custom[adapter + '.' + instance].smartName : undefined;
                }
            }
        } else
        if (!noCommon) {
            return states[id].common.smartName;
        } else {
            return (states[id] &&
                states[id].common &&
                states[id].common.custom &&
                states[id].common.custom[adapter + '.' + instance]) ?
                states[id].common.custom[adapter + '.' + instance].smartName || null : null;
        }
    }

    function initSelectId(callback) {
        if (selectId) {
            return callback(selectId);
        }
        socket.emit('getObjects', function (err, objs) {
            selectId = $('#dialog-select-member').selectId('init',  {
                noMultiselect: true,
                objects: objs,
                imgPath:       '../../lib/css/fancytree/',
                filter:        {type: 'state'},
                name:          'scenes-select-state',
                texts: {
                    select:          _('Select'),
                    cancel:          _('Cancel'),
                    all:             _('All'),
                    id:              _('ID'),
                    name:            _('Name'),
                    role:            _('Role'),
                    room:            _('Room'),
                    value:           _('Value'),
                    selectid:        _('Select ID'),
                    from:            _('From'),
                    lc:              _('Last changed'),
                    ts:              _('Time stamp'),
                    wait:            _('Processing...'),
                    ack:             _('Acknowledged'),
                    selectAll:       _('Select all'),
                    unselectAll:     _('Deselect all'),
                    invertSelection: _('Invert selection')
                },
                columns: ['image', 'name', 'role', 'room']
            });
            callback(selectId);
        });
    }

    function initDialog() {
        var $editDialog = $('#edit_dialog');
        if (!$editDialog.data('inited')) {
            $editDialog.data('inited', true);
            $editDialog.dialog({
                autoOpen: false,
                title:    _('Edit smart name'),
                modal:    true,
                width:    600,
                height:   230,
                buttons: [
                    {
                        id:    'edit-ok',
                        text: _('Ok'),
                        click: function () {
                            $(this).dialog('close');
                            var callback = $('#edit_dialog').data('callback');
                            if (typeof callback === 'function') callback();
                        }
                    },
                    {
                        text: _('Cancel'),
                        click: function () {
                            $(this).dialog('close');
                        }
                    }
                ]
            });
            $('#edit_name').keyup(function (e) {
                if (e.keyCode === 13) {
                    setTimeout(function () {
                        $('#edit-ok').trigger('click');
                    }, 100);
                }
            });
        }
    }

    function getSelect(id, type) {
        // type = '-', false or number [5-100]
        if (type !== false) {
            var text = '<select data-id="' + id + '" class="by-on-edit">';
            text += '<option value="-" ' + (type === '-' ? 'selected' : '') + '>' + _('last value') + '</option>';
            for (var i = 5; i <= 100; i += 5) {
                text += '<option value="' + i + '" ' + (type === i.toString() ? 'selected' : '') + '>' + i + '%</option>';
            }
            text += '</select>';
            return text;
        } else {
            return '';
        }
    }

    const SMARTTYPES = ["LIGHT", "SWITCH", "THERMOSTAT", "ACTIVITY_TRIGGER","SCENE_TRIGGER","SMARTPLUG","SMARTLOCK","CAMERA"]

    function getTypeSelect(id, type) {
        // type = '-', false or number [5-100]
        if (type !== false) {
            var text = '<select data-id="' + id + '" class="type-edit">';
            text += '<option value="" ' + ((!type) ? 'selected' : '') + '>' + _('no type') + '</option>';
            for(var i=0; i<SMARTTYPES.length; i++) {
                text += '<option value="' + SMARTTYPES[i] + '" ' + (type === SMARTTYPES[i] ? 'selected' : '') + '>' + SMARTTYPES[i] + '</option>';
            }
            text += '</select>';
            return text;
        } else {
            return '';
        }
    }

    function updateDevices(delay) {
        if (delay) {
            if (devTimer) clearTimeout(devTimer);
            devTimer = setTimeout(function () {
                devTimer = null;
                updateDevices();
            }, delay);
            return;
        }
        sendTo(null, 'browse', null, function (list) {
            if (list) {
                var text = '<tr><th style="width: 30%">' + _('Smart name') + '</th><th style="width: 100px">' + _('Commands') + '</th><th style="width: 70%">' + _('Addresses') + '<span style="float: right; padding-right: 130px">' + _('Types') + '</span><span style="float: right; padding-right: 130px">' + _('by ON') + '</span></th></tr>';

                for (var j = 0; j < list.length; j++) {
                    if (list[j].additionalApplianceDetails.group || !list[j].additionalApplianceDetails.nameModified) {
                        text += '<tr><td class="smart-name"  style="white-space: nowrap;">' + list[j].friendlyName + '</td>';
                    } else {
                        text += '<tr><td class="smart-name"  style="white-space: nowrap; font-style: italic" title="' + _('modified') + '">' + list[j].friendlyName + '</td>';
                    }
                    // Type
                    var actions = [];
					if (!list[j].actions) {
						console.log('Something went wrong');
						continue;
					}
					for (var a = 0; a < list[j].actions.length; a++) {
                        if (actionsMapping[list[j].actions[a]]) {
                            actions.push(actionsMapping[list[j].actions[a]]);
                        } else {
                            actions.push(list[j].actions[a]);
                        }
                    }
                    // place ON /OFF first
                    var pos = actions.indexOf(actionsMapping.turnOff);
                    if (pos !== -1) {
                        actions.splice(pos, 1);
                        actions.unshift(actionsMapping.turnOff)
                    }
                    pos = actions.indexOf(actionsMapping.turnOn);
                    if (pos !== -1) {
                        actions.splice(pos, 1);
                        actions.unshift(actionsMapping.turnOn)
                    }

                    text += '<td style="white-space: nowrap;">' + actions.join(' ') + '</td>';

                    text += '<td>';
                    text += '<table style="width: 100%" class="smart-table">';
                    
                    if (list[j].additionalApplianceDetails.group) {
                        var channels = list[j].additionalApplianceDetails.channels;
                        var names = list[j].additionalApplianceDetails.names;
                        var types = list[j].additionalApplianceDetails.byONs;
                        var smarttypes = list[j].additionalApplianceDetails.smartTypes;

                        for (var chan in channels) {
                            for (var i=0; i<channels[chan].length; i++) {
                                var k = chan+"."+channels[chan][i].split(' ')[0];
                                text += '<tr><td title="' + k + '">' + (names[k] || k) + '</td>';
                                text += '<td style="width: 95px">' + getSelect(k, types[k]) + '</td>';
                                text += '<td style="width: 95px">' + getTypeSelect(k, smarttypes[k]) + '</td>';
                                text += '<td style="width: 95px"><button data-id="' + k + '" class="button-delete"></button></td></tr>';
                            }
                        }
                    } else {
                        var name = list[j].additionalApplianceDetails.name;
                        text += '<tr><td title="' + (list[j].additionalApplianceDetails.id || '') + '">';
                        text +=  name;
                        text += '</td>';
                        text += '<td style="width: 95px">' + getSelect(list[j].additionalApplianceDetails.id, list[j].additionalApplianceDetails.byON) + '</td>';
                        text += '<td style="width: 95px">' + getTypeSelect(list[j].additionalApplianceDetails.id, list[j].additionalApplianceDetails.smartType) + '</td>';
                        text += '<td style="width: 95px"><button data-id="' + list[j].additionalApplianceDetails.id + '" class="button-delete"></button><button data-value="' + (list[j].additionalApplianceDetails.friendlyNames ? list[j].additionalApplianceDetails.friendlyNames : list[j].friendlyName) + '" data-id="' + list[j].additionalApplianceDetails.id + '" class="button-edit"></button></td>';
                        text += '</td></tr>';
                    }
                    text += '</table>';
                    text += '</td></tr>';
                }

                var $smartTable = $('#smart_table');
                $smartTable.html(text).find('.button-delete').click(function () {
                    var $this = $(this);
                    var id = $this.data('id');

                    confirmMessage(_('Device will be disabled.'), _('Are you sure?'), 'alert', function (result) {
                        if (result) {
                            $this.parent().addClass('smart-changed');
                            socket.emit('getObject', id, function (err, obj) {
                                disableSmartName(obj);
                                socket.emit('setObject', id, obj, function (err) {
                                    //updateDevices(2000);
                                    if (err) {
                                        window.alert(err);
                                    }
                                });
                            });
                        }
                    });
                }).button({icons: {primary: 'ui-icon-trash'}, text: false}).css({width: '26px', height: '26px'});

                $smartTable.find('.by-on-edit').change(function () {
                    var $this = $(this);
                    var id    = $this.data('id');
                    var val   = $this.val();
                    $this.addClass('smart-changed');
                    socket.emit('getObject', id, function (err, obj) {
                        updateSmartName(obj, null, undefined, val);
                        socket.emit('setObject', id, obj, function (err) {
                            //updateDevices(2000);
                            if (err) {
                                window.alert(err);
                            }
                        });
                    });
                });
                
                $smartTable.find('.type-edit').change(function () {
                    var $this = $(this);
                    var id    = $this.data('id');
                    var val   = $this.val();
                    $this.addClass('smart-changed');
                    socket.emit('getObject', id, function (err, obj) {
                        updateSmartName(obj, null, undefined, undefined, val);
                        socket.emit('setObject', id, obj, function (err) {
                            //updateDevices(2000);
                            if (err) {
                                window.alert(err);
                            }
                        });
                    });
                });

                $smartTable.find('.button-edit').click(function () {
                    var $this = $(this);
                    var $editDialog = $('#edit_dialog');
                    $editDialog.data('id', $this.data('id'));
                    $('#edit_name').val($this.data('value'));

                    initDialog();

                    $editDialog.data('callback', function () {
                        var id = $('#edit_dialog').data('id');

                        var $devices = $('#smart_table').find('.button-edit');

                        var val   = $('#edit_name').val();
                        var found = false;
                        $devices.each(function () {
                            if ($(this).data('value') === val && $(this).data('id') !== id) {
                                found = true;
                                return false;
                            }
                        });

                        if (found) {
                            showMessage(_('Duplicate name'), _('Error'), 'alert');
                            return;
                        }

                        //noinspection JSJQueryEfficiency
                        $devices.find('[data-id="' + id + '"]').parent().addClass('smart-changed');

                        idToNavigate = id;
                        socket.emit('getObject', id, function (err, obj) {
                            updateSmartName(obj, null, $('#edit_name').val());
                            socket.emit('setObject', id, obj, function (err) {
                                //updateDevices(2000);
                                if (err) {
                                    window.alert(err);
                                }
                            });
                        });
                    });
                    $editDialog.dialog('open');
                }).button({icons: {primary: 'ui-icon-pencil'}, text: false}).css({width: '26px', height: '26px'});

                if (idToEdit) {
                    $smartTable.find('.button-edit[data-id="' + idToEdit + '"]').trigger('click');
                    idToEdit = null;
                }
                if (idToNavigate) {
                    var $td = $smartTable.find('.button-edit[data-id="' + idToNavigate + '"]');
                    $td[0].scrollIntoView();
                    $td.parent().parent().addClass('highlight');
                    idToNavigate = null;
                }
            }
            filter();
        });
    }

    function disableSmartName(states, id) {
        var obj;
        if (!id) {
            obj = states;
        } else {
            obj = states[id];
        }
        if (noCommon) {
            obj.common.custom = obj.common.custom || {};
            obj.common.custom[adapter + '.' + instance] = obj.common.custom[adapter + '.' + instance] || {};
            obj.common.custom[adapter + '.' + instance].smartName = false;
        } else {
            obj.common.smartName = false;
        }
    }

    function enableSmartName(states, id) {
        var obj;
        if (!id) {
            obj = states;
        } else {
            obj = states[id];
        }
        if (noCommon) {
            obj.common.custom = obj.common.custom || {};
            obj.common.custom[adapter + '.' + instance] = obj.common.custom[adapter + '.' + instance] || {};
            obj.common.custom[adapter + '.' + instance].smartName = {};
        } else {
            obj.common.smartName = {};
        }
    }

    function removeSmartName(states, id) {
        var obj;
        if (!id) {
            obj = states;
        } else {
            obj = states[id];
        }
        if (noCommon) {
            if (obj.common && obj.common.custom && obj.common.custom[adapter + '.' + instance]) {
                delete obj.common.custom[adapter + '.' + instance];
            }
        } else {
            obj.common.smartName = null;
        }
    }

    function updateSmartName(states, id, newSmartName, byON, smartType) {
        var obj;
        if (!id) {
            obj = states;
        } else {
            obj = states[id];
        }

        // convert Old format
        if (typeof obj.common.smartName === 'string') {
            var nnn = obj.common.smartName;
            obj.common.smartName = {};
            obj.common.smartName[language] = nnn;
        }

        // convert old settings
        if (obj.native && obj.native.byON) {
            delete obj.native.byON;
            var _smartName = obj.common.smartName;

            if (!_smartName || typeof _smartName !== 'object') {
                _smartName = {
                    en:     _smartName
                };
                _smartName[language] = _smartName.en;
            }
            obj.common.smartName = _smartName;
        }
        if (smartType !== undefined) {
            if (noCommon) {
                obj.common.custom = obj.common.custom || {};
                obj.common.custom[adapter + '.' + instance] = obj.common.custom[adapter + '.' + instance] || {};
                obj.common.custom[adapter + '.' + instance].smartName = obj.common.custom[adapter + '.' + instance].smartName || {};
                obj.common.custom[adapter + '.' + instance].smartName.smartType = smartType;
            } else {
                obj.common.smartName = obj.common.smartName || {};
                obj.common.smartName.smartType = smartType;
            }
        }
        if (byON !== undefined) {
            if (noCommon) {
                obj.common.custom = obj.common.custom || {};
                obj.common.custom[adapter + '.' + instance] = obj.common.custom[adapter + '.' + instance] || {};
                obj.common.custom[adapter + '.' + instance].smartName = obj.common.custom[adapter + '.' + instance].smartName || {};
                obj.common.custom[adapter + '.' + instance].smartName.byON = byON;
            } else {
                obj.common.smartName = obj.common.smartName || {};
                obj.common.smartName.byON = byON;
            }
        }
        if (newSmartName !== undefined) {
            var smartName;
            if (noCommon) {
                obj.common.custom = obj.common.custom || {};
                obj.common.custom[adapter + '.' + instance] = obj.common.custom[adapter + '.' + instance] || {};
                obj.common.custom[adapter + '.' + instance].smartName = obj.common.custom[adapter + '.' + instance].smartName || {};
                smartName = obj.common.custom[adapter + '.' + instance].smartName;
            } else {
                obj.common.smartName = obj.common.smartName || {};
                smartName = obj.common.smartName;
            }
            smartName[language] = newSmartName;

            if (smartName && (!smartName[language] || 
			(smartName[language] === obj.common.name && 
				(!obj.common.role || obj.common.role.indexOf('button') >=0)))) {
                delete smartName[language];
                var empty = true;
                for (var key in smartName) {
                    if (smartName.hasOwnProperty(key)) {
                        empty = false;
                        break;
                    }
                }
                if (empty) {
                    if (noCommon) {
                        if (obj.common.custom[adapter + '.' + instance].smartName.byON === undefined) {
                            delete obj.common.custom[adapter + '.' + instance];
                        } else {
{'fraction_non_alphanumeric': 0.15355441677765988, 'fraction_numerical': 0.0043343793033388265, 'mean_word_length': 1.2260301507537688, 'pattern_counts': {'":': 0, '<': 185, '<?xml version=': 0, '>': 176, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1824672', 'n_tokens_mistral': 11875, 'n_tokens_neox': 11023, 'n_words': 2084}