/**
 * Created by user on 9/30/15.
 */

const devlistTbodyId = '#devlist_tbody';

function setDeviceLine(data) {
    $('#device_' + data.deviceName).html(
        '<td><b>' + data.deviceName + '</b></td>' +
        '<td>' + data.deviceType + '</td>' +
        '<td ' + ((data.deviceStatus == "online") ?
            ('class="success">online') :
            ('class="danger">' + data.deviceStatus)) +
        '</td>'
    );
}

function requestDeviceState(device) {
    var req = {
        subsystem: device,
        reqtype: '@GET_STATE'
    };
    $.post("flugegeheimen", JSON.stringify(req), setDeviceLine, 'json');
}

function jsonToDevicesList(data) {
    var tbody = '';
    for (i = 0; i < data.devices_list.length; i++) {
        tbody = tbody + '<tr id="device_' + data.devices_list[i].name + '"><td><b>' + data.devices_list[i].name +
            '</b></td><td>' + data.devices_list[i].type + '</td><td class="danger">unknown</td></tr>';
    }
    console.log(tbody);
    $(devlistTbodyId).html(tbody);
    for (i = 0; i < data.devices_list.length; i++) {
        requestDeviceState(data.devices_list[i].name);
    }
}

function refreshDevicesList() {
    FlugDeviceManager.GetDevicesList(jsonToDevicesList);
}

function DeviceManager(container, controlsEnabled) {
    this.m_container = $(container);
    this.m_datastore = 'DEVICEMANAGER';
    this.Request = function (req, callback) {
        if ('subsystem' in req) {
        } else {
            req['subsystem'] = 'devmgr';
        }
        $.post('/flugegeheimen', JSON.stringify(req), callback, 'json');
    };

    this.BuildInterface = function () {
        var html =
            '<div class="col-md-12" id="devices_controls"></div><hr>' +
            '<div class="col-md-12" id="devices_table"></div>';
        this.m_container.html(html);
    };

    this.UpdateDrivers = function (ev) {
        var self = ev.data;
        self.Request({reqtype: 'getDrivers'},
            function (resp) {
                var html = '';
                self.m_drivers = resp.drivers;
                for (var drv in resp.drivers) {
                    html +=
                        '<option value="' +
                        resp.drivers[drv] +
                        '">' +
                        resp.drivers[drv] +
                        '</option>';
                }
                $('#devadd_drivers').html(html);
            })
    };

    this.UpdateDevices = function (ev) {
        var self = ev.data;
        self.Request({reqtype: 'getDevices'},
            function (resp) {
                var html = '';
                self.m_devices = resp.devices;
                for (var dtype in resp.devices) {
                    html +=
                        '<div class="panel panel-info">' +
                        '<div class="panel-heading">' + dtype + '</div>' +
                        '<div class="panel-body">' +
                        '<table class="table table-responsive">' +
                        '<thead><tr><th></th></tr></thead>';
                    for (var dev in resp.devices[dtype]) {
                        var device = resp.devices[dtype][dev];
                        console.log({dev: device, type: dtype});
                        html +=
                            '<tr>' +
                            '<td width="40%">' +
                            '<a href="/devices/' + dtype + '.html?' + device + '">' +
                            device + '</a></td>' +
                            '<td width="30%">' + dtype + '</td>' +
                            '<td width="10%" id="dev_status_' + device + '">busy</td>' +
                            '<td width="20%">' +
                            '<div class="btn-group pull-right" role="group">' +
                            '<button class="btn btn-primary" id="config_btn_' +
                            device + '">' +
                            '<span class="glyphicon glyphicon-cog"></span></button>' +
                            '<button class="btn btn-danger" id="reboot_btn_' +
                            device + '">' +
                            '<span class="glyphicon glyphicon-refresh"></span></button>' +
                            '<button class="btn btn-danger" id="remove_btn_' +
                            device + '">' +
                            '<span class="glyphicon glyphicon-remove"></span></button>' +
                            '</div>' +
                            '</td>' +
                            '</tr>';
                    }
                    html += '</table></div></div>';
                    //self.m_devTable.html(html);
                }
                self.m_devTable.html(html);

                for (var dtype in resp.devices) {
                    for (var dev in resp.devices[dtype]) {
                        var device = resp.devices[dtype][dev];
                        $('#remove_btn_' + device).on(
                            'click', self, self.RemoveDevice
                        );

                        $('#reboot_btn_' + device).on(
                            'click', self, self.RebootDevice
                        );

                        $('#config_btn_' + device).on(
                            'click', self, self.OpenDeviceConfig
                        );

                        self.GetDeviceStatus(device);
                    }
                }
            }
        );
    };

    this.GetDeviceStatus = function (device) {
        this.Request(
            {reqtype: '@GET_STATE', subsystem: device},
            function (resp) {
                if (resp.status == "success") {
                    $('#dev_status_' + device).text(resp.state);
                } else {
                    $('#dev_status_' + device).text('failed');
                }
            }
        );
    };


    this.BuildControls = function () {
        var html =

                '<div class="btn-group" role="group">' +
                //'<div class="dropdown">' +
                '<button data-toggle="dropdown" ' +
                'class="btn btn-default" id="load_configuration">' +
                '<span class="glyphicon glyphicon-open-file"></span>' +
                'Load Configuration' +
                '<span class="caret"></span>' +
                '</button>' +
                '  <ul class="dropdown-menu" id="configurations_list"></ul>' +
                //'</div>' +
                '<button class="btn btn-default" id="save_configuration">' +
                '<span class="glyphicon glyphicon-save-file"></span>' +
                'Save Configuration</button>' +
                '</div>' +

                '<div class="btn-group pull-right" role="group">' +
                '<button class="btn btn-success" id="refresh_devices">' +
                '<span class="glyphicon glyphicon-refresh"></span>' +
                'Refresh</button>' +
                '<button data-toggle="modal" data-target="#add_device_modal" ' +
                'class="btn btn-primary" id="add_device">' +
                '<span class="glyphicon glyphicon-plus"></span>' +
                'Add Device</button>' +
                /*'<button class="btn btn-default" id="config_device">' +
                 '<span class="glyphicon glyphicon-cog"></span></button>' +*/

                '</div>' +
                '' +
                '' +
                '<div class="modal fade" id="add_device_modal" ' +
                'tabindex="-1" role="dialog">' +
                '<div class="modal-dialog">' +
                '<div class="modal-content">' +
                '<div class="modal-header">' +
                '<button type="button" class="close" ' +
                'data-dismiss="modal" aria-label="Close">' +
                '<span aria-hidden="true">&times;</span></button>' +
                '<h4 class="modal-title">Add device</h4>' +
                '</div>' +
                '<div class="modal-body">' +
                '<label style="width: 30%;" for="devadd_name">' +
                'Device Name: </label>' +
                '<input style="width: 70%;" type="text" id="devadd_name"><br>' +
                '<label style="width: 30%;" for="devadd_drivers">' +
                'Device Driver: </label>' +
                '<select style="width: 70%;" name="devadd_type" ' +
                'id="devadd_drivers"></select><hr>' +
                '<label for="devadd_config">Device Configuration: </label><br>' +
                '<textarea style="width: 100%; resize: none; ' +
                'overflow: auto; font-family: monospace;" ' +
                'name="devadd_conf" id="devadd_config" rows="10">' +
                '</textarea>' +
                '</div>' +
                '<div class="modal-footer">' +
                '<button type="button" class="btn btn-default" ' +
                'data-dismiss="modal">Close</button>' +
                '<button id="devadd_ok" type="button" class="btn btn-primary">' +
                '<span class="glyphicon glyphicon-plus"></span>' +
                'Add Device</button>' +
                '</div>' +
                '</div><!-- /.modal-content -->' +
                '</div><!-- /.modal-dialog -->' +
                '</div><!-- /.modal -->' +
                '' +
                '' +
                '<div class="modal fade" id="config_device_modal" ' +
                'tabindex="-1" role="dialog">' +
                '<div class="modal-dialog">' +
                '<div class="modal-content">' +
                '<div class="modal-header">' +
                '<button type="button" class="close" ' +
                'data-dismiss="modal" aria-label="Close">' +
                '<span aria-hidden="true">&times;</span></button>' +
                '<h4 class="modal-title">Configure device</h4>' +
                '</div>' +

                '<div class="modal-body">' +
                '<h4 id="devconf_name">Unkmown</h4>' +
                '<label for="devadd_config">Device Configuration: </label><br>' +
                '<textarea style="width: 100%; resize: none; ' +
                'overflow: auto; font-family: monospace;" ' +
                'id="devconf_config" rows="10">' +
                '</textarea>' +
                '</div>' +

                '<div class="modal-footer">' +
                '<button type="button" class="btn btn-default" ' +
                'data-dismiss="modal">Close</button>' +
                '<button id="devconf_ok" type="button" class="btn btn-primary">' +
                'Save Configuration</button>' +
                '</div>' +
                '</div><!-- /.modal-content -->' +
                '</div><!-- /.modal-dialog -->' +
                '</div><!-- /.modal -->'
            ;

        this.m_devControls.html(html);
        $('#refresh_devices').on('click', this, this.UpdateDevices);
        $('#add_device').on('click', this, this.UpdateDrivers);
        $('#devadd_ok').on('click', this, this.AddDevice);
        $('#devconf_ok').on('click', this, this.SaveDeviceConfig);
        $('#save_configuration').on('click', this, this.OnSaveConfig);
        $('#load_configuration').on('click', this, this.OnLoadConfig);
        $('#devadd_name').val("");
        $('#devadd_config').val("{}")

    };

    this.SaveDeviceConfig = function (ev) {
        var self = ev.data;
        var device = self.m_currentDevice;
        var confStr = $('#devconf_config').val();
        if (self.CheckConfig(confStr)) {
            self.Request(
                {
                    subsystem: device,
                    config: JSON.parse(confStr),
                    reqtype: '@UPDATE_CONFIG'
                },
                function (resp) {
                    if (resp.status != 'success') {
                        alert('Error: ' + resp.description);
                    }
                    self.GetDeviceStatus(device);
                    $('#config_device_modal').modal('hide');
                }
            );
        } else {
            alert("Wrong JSON format")
        }
    };

    this.OpenDeviceConfig = function (ev) {
        var self = ev.data;
        console.log(ev.target);
        var device = $(this).attr('id').replace('config_btn_', '');
        self.m_currentDevice = device;
        $('#devconf_name').text(device);
        self.Request(
            {
                subsystem: device,
                reqtype: '@GET_CONFIG'
            },
            function (resp) {
                if (resp['status'] == 'success') {
                    $('#devconf_config').val(JSON.stringify(resp.config, null, 2));
                    $('#config_device_modal').modal('show');
                } else {
                    alert('Error: ' + resp.description);
                }
            }
        );
    };

    this.CheckConfig = function (cfg) {
        try {
            JSON.parse(cfg);
        } catch (e) {
            return false;
        }
        return true;
    };

    this.ClearDeviceFields = function () {
        $('#devadd_name').val("");
        $('#devadd_config').val("{}")
    };

    this.AddDevice = function (ev) {
        var self = ev.data;
        var cfg = $('#devadd_config').val();
        var req = {
            reqtype: 'registerDevice',
            name: $('#devadd_name').val(),
            driver: $('#devadd_drivers').val(),
        };

        if (cfg != '') {
            if (!self.CheckConfig(cfg)) {
                alert('Wrong JSON format')
                return;
            }
            req.config = JSON.parse(cfg)
        }
        self.Request(
            req, function (resp) {
                console.log(resp);
                if (resp.status == 'success') {
                    self.UpdateDevices({data: self});
                    $('#add_device_modal').modal('hide');
                    self.ClearDeviceFields();
                } else {
                    alert(resp.description);
                }
            }
        )

    };

    this.RemoveDevice = function (ev) {
        var self = ev.data;
        var req = {
            reqtype: 'stopDevice',
            device: $(this).attr('id').replace('remove_btn_', '')
        };
        self.Request(req, function (resp) {
            self.UpdateDevices({data: self});
        });
    };

    this.RebootDevice = function (ev) {
        var self = ev.data;
        var req = {
            reqtype: '@REBOOT',
            subsystem: $(this).attr('id').replace('reboot_btn_', '')
        };
        self.Request(req, function (resp) {
            self.UpdateDevices({data: self});
        });
    };

    this.MultiRequest = function (requests, callback) {
        var self = this;
        var deferreds = [];
        for (var req in requests) {
            var def = $.post("/flugegeheimen",
                JSON.stringify(requests[req]), "json");
            deferreds.push(def);
        }
        //console.log('deffereds: ', deferreds);
        $.when.apply($, deferreds).then(function () {
            callback.apply(self, arguments);
        });
    };

    this.BuildConfigurationStruct = function (configName) {
        var self = this;
        self.m_configurationStructure = [];
        for (var dtype in self.m_devices) {
            for (var dev in self.m_devices[dtype]) {
                var device = self.m_devices[dtype][dev];
                self.m_configurationStructure.push({device: device, driver: dtype});
            }
        }



        var requests = $.map(self.m_configurationStructure, function (device) {
            return {
                subsystem: device.device,
                reqtype: '@GET_CONFIG'
            };
        });

        self.MultiRequest(requests, function () {
            for (var arg in arguments) {
                self.m_configurationStructure[arg].config = arguments[arg][0].config;
            }
            self.SaveConfiguration(configName, self.m_configurationStructure);
        });

    };

    this.PrepareDatastore = function () {
        var req = {
            subsystem: 'database',
            reqtype: 'registerDatastore',
            name: this.m_datastore
        };

        this.Request(
            req, function (resp) {
            }
        );

    };

    this.FetchConfigurationsList = function () {
        //return {data: [{name: 'asdf'}, {name: 'asadfasf'}]}
        var req = {
            subsystem: 'database',
            reqtype: 'find',
            datastore: 'datastore_' + this.m_datastore,
            search: {},
            fields: {name: 1}
        };

        var self = this;

        this.Request(
            req, function (resp) {
                var list = $('#configurations_list');
                var html = '';
                for (var cfg in resp.data) {
                    html += '<li><a href="#" id="config_load_' +
                        resp.data[cfg]._id.$oid +
                        '">' + resp.data[cfg].name + '</a></li>';
                }
                list.html(html);
                for (var cfg in resp.data) {
                    $('#config_load_' + resp.data[cfg]._id.$oid)
                        .on('click', self, self.LoadConfiguration)
                }
            }
        );
    };

    this.LoadConfiguration = function (ev) {
        var self = ev.data;
        var configid = $(ev.target).attr('id').replace('config_load_','');
        console.log(configid);
        var req = {
            subsystem: 'database',
            reqtype: 'find',
            datastore: 'datastore_' + self.m_datastore,
            search: {_id: {$oid: configid}},
            fields: {}
        };

        self.Request(req, function (resp) {
            var newConfig = resp.data[0].config;
            console.log(newConfig);
            self.ApplyConfig(newConfig);
        });
    };

    this.ApplyConfig = function (config) {
        var self = this;
        var devs = [];
        for (var dtype in self.m_devices) {
            for (var dev in self.m_devices[dtype]) {
                devs.push(self.m_devices[dtype][dev]);
            }
        }
        var deferrs = $.map(devs, function (device) {
            var req = {
                subsystem: 'devmgr',
                reqtype: 'stopDevice',
                device: device
            };
            return $.post('/flugegeheimen', JSON.stringify(req), 'json');
        });
        $.when.apply(deferrs).then(function () {

            var applyDeferr = $.map(config, function (device) {
                var req = {
                    subsystem: 'devmgr',
                    reqtype: 'registerDevice',
                    name: device.device,
                    driver: device.driver,
                    config: device.config
                };
                return $.post('/flugegeheimen', JSON.stringify(req), 'json');
            });
            $.when.apply(applyDeferr).then(function () {self.UpdateDevices({data:self});});

        });
    };

    this.SaveConfiguration = function (configurationName, conf) {
        var req = {
            subsystem: 'database',
            reqtype: 'update',
            collection: 'datastore_' + this.m_datastore,
            search: {name: configurationName},
            update: {name: configurationName, config: conf},
            upsert: true
        };
        var self = this;
        this.Request(
            req, function (resp) {
                if (resp.status != 'success') {
                    alert('Failed to save configuration: ' + resp.description);
                }
            }
        );
    };

    this.OnSaveConfig = function (ev) {
        var self = ev.data;
        var confName = prompt("Configuration name", "");

        if (confName != null && confName != "") {
            self.BuildConfigurationStruct(confName);
        }
    };

    this.OnLoadConfig = function (ev) {
        var self = ev.data;
        self.FetchConfigurationsList();
    };

    this.BuildInterface();
    this.m_devTable = $("#devices_table");
    this.m_devControls = $("#devices_controls");
    this.BuildControls();
    this.UpdateDevices({data: this});
    this.PrepareDatastore();
}