angular.module('IOLabApp').factory('configService', function () {
    'use strict';

    var colorRed = '#BB0000';
    var colorBlue = '#0000BB';
    var colorGreen = '#008800';

    var dongleModes = {};
    dongleModes[1] = { desc: 'IDLE' };
    dongleModes[2] = { desc: 'PAIRING' };
    dongleModes[4] = { desc: 'PAIRED' };
    dongleModes[8] = { desc: 'CONNECTED' };
    dongleModes[16] = { desc: 'DATA' };

    var sensors = {};
    sensors[1] = {
        code: 1,
        desc: 'Accelerometer',
        shortDesc: 'Accel',
        label: 'a',
        unit: 'm/s²',
        legends: ['Ax', 'Ay', 'Az'],
        pathColors: [colorRed, colorBlue, colorGreen],
        scales: [-20, 20],
        minScalingRate: 5,
        autoScaleY: false
    };

    sensors[2] = {
        code: 2,
        desc: 'Magnetometer',
        shortDesc: 'Magn',
        label: 'B',
        unit: 'µT',
        legends: ['Bx', 'By', 'Bz'],
        pathColors: [colorRed, colorBlue, colorGreen],
        scales: [-150, 150],
        minScalingRate: 5,
        autoScaleY: false
    };

    sensors[3] = {
        code: 3,
        desc: 'Gyroscope',
        shortDesc: 'Gyro',
        label: 'Ω',
        unit: 'rad/s',
        legends: ['Ωx', 'Ωy', 'Ωz'],
        pathColors: [colorRed, colorBlue, colorGreen],
        scales: [-20, 20],
        minScalingRate: 5,
        autoScaleY: false
    };

    sensors[4] = {
        code: 4,
        desc: 'Barometer',
        shortDesc: 'Baro',
        label: 'P',
        unit: 'kPa',
        legends: ['Pressure'],
        scales: [0, 120],
        autoScaleY: false
    };

    sensors[6] = {
        code: 6,
        desc: 'Microphone',
        shortDesc: 'Micro',
        scales: [0, 10],
        fftThreshold: 25, // Hz
        autoScaleY: false
    };

    sensors[7] = {
        code: 7,
        desc: 'Light',
        shortDesc: 'Light',
        scales: [0, 10],
        autoScaleY: false
    };

    sensors[8] = {
        code: 8,
        desc: 'Force',
        shortDesc: 'Force',
        label: 'Fᵧ',
        unit: 'N',
        legends: ['Fᵧ'],
        pathColors: [colorBlue],
        scales: [-5, 5],
        autoScaleY: false
    };

    sensors[9] = {
        code: 9,
        desc: 'Wheel',
        shortDesc: 'Wheel',
        subCharts: [
            { desc: 'Position',     label: 'rᵧ', unit: 'm',    legends: ['rᵧ'], autoScaleY: false, pathColors: [colorRed], scales: [-2, 2] },
            { desc: 'Velocity',     label: 'vᵧ', unit: 'm/s',  legends: ['vᵧ'], autoScaleY: false, pathColors: [colorGreen], scales: [-3, 3] },
            { desc: 'Acceleration', label: 'aᵧ', unit: 'm/s²', legends: ['aᵧ'], autoScaleY: false, pathColors: [colorBlue], scales: [-30, 30] }
        ],
        timeAverageIdx: 2,
        reverseAxis: false
    };

    sensors[10] = { // 0x0A
        code: 10,
        desc: 'Electrocardiogram (3)',
        shortDesc: 'ECG3', // ECG (requires plugin)
        label: 'A',
        unit: 'mV',
        legends: ['V1', 'V2', 'V3'],
        pathColors: [colorRed, colorBlue, colorGreen],
        autoScaleY: false
    };

    sensors[11] = { // 0x0B
        code: 11,
        desc: 'Battery',
        shortDesc: 'Bat',
        label: 'T',
        unit: 'V',
        legends: ['Battery'],
        scales: [0, 4],
        autoScaleY: false
    };

    sensors[12] = { // 0x0C
        code: 12,
        desc: 'High Gain',
        shortDesc: 'HG',
        label: 'A',
        unit: 'mV',
        legends: ['Voltage'],
        scales: [-1, 1],
        autoScaleY: false
    };

    sensors[13] = { // 0x0D
        code: 13,
        desc: 'Digital',
        shortDesc: 'Digi',
        scales: [0, 5],
        autoScaleY: false
    };

    sensors[21] = { // 0x15
        code: 21,
        desc: 'Analog 7',
        shortDesc: 'Ana7',
        label: 'A',
        unit: 'V',
        legends: ['Voltage'],
        scales: [0, 4],
        autoScaleY: false
    };

    sensors[22] = { // 0x16
        code: 22,
        desc: 'Analog 8',
        shortDesc: 'Ana8',
        label: 'A',
        unit: 'V',
        legends: ['Voltage'],
        scales: [0, 4],
        autoScaleY: false
    };

    sensors[23] = { // 0x17
        code: 23,
        desc: 'Analog 9',
        shortDesc: 'Ana9',
        label: 'A',
        unit: 'V',
        legends: ['Voltage'],
        scales: [0, 4],
        autoScaleY: false
    };

    sensors[26] = { // 0x1A
        code: 26,
        desc: 'Thermometer',
        shortDesc: 'Therm',
        label: 'T',
        unit: '°C',
        legends: ['Temp.'],
        pathColors: [colorBlue],
        scales: [0, 40],
        autoScaleY: false
    };

    sensors[241] = { // 0xF1 // Electrocardiogram
        code: 241,
        desc: 'Electrocardiogram (9)',
        shortDesc: 'ECG9',
        unit: 'mV',
        legends: ['I', 'II', 'III', 'aVR', 'aVL', 'aVF', 'V1', 'V3', 'V6'],
        pathColors: ['#819263', '#3ca13b', '#546f6f', '#342fdd', '#49a6ff', '#515095', '#c34947', '#fa3430', '#a73431'],
        timeAverageIdx: 2,
        scales: [-0.5, 0.5],
        minScalingRate: 5,
        autoScaleY: true
    };

    var fixedConfigs = {};
    fixedConfigs[1] = {
        desc: 'Gyroscope',
        highSpeed: false,
        frequencies: [100, 200, 400],
        sensors: [
            { sensorKey: 3, sampleRate: 380 }
        ]
    };

    fixedConfigs[2] = {
        desc: 'Accelerometer',
        highSpeed: false,
        frequencies: [100, 200, 400],
        sensors: [
            { sensorKey: 1, sampleRate: 400 }
        ]
    };

    fixedConfigs[3] = {
        desc: 'Orientation',
        highSpeed: false,
        frequencies: [100],
        sensors: [
            { sensorKey: 1, sampleRate: 100 },
            { sensorKey: 2, sampleRate: 80 },
            { sensorKey: 3, sampleRate: 95 },
            { sensorKey: 12, sampleRate: 100 }
        ]
    };

    fixedConfigs[4] = {
        desc: 'Mini-motion',
        highSpeed: false,
        frequencies: [100, 200],
        sensors: [
            { sensorKey: 1, sampleRate: 200 },
            { sensorKey: 8, sampleRate: 200 },
            { sensorKey: 9, sampleRate: 100 }
        ]
    };

    fixedConfigs[5] = {
        desc: 'Pendulum',
        highSpeed: false,
        frequencies: [100],
        sensors: [
            { sensorKey: 1, sampleRate: 100 },
            { sensorKey: 3, sampleRate: 95 },
            { sensorKey: 8, sampleRate: 100 }
        ]
    };

    fixedConfigs[6] = {
        desc: 'Ambient',
        highSpeed: false,
        frequencies: [50, 100, 200, 400],
        sensors: [
            { sensorKey: 4, sampleRate: 100 },
            { sensorKey: 7, sampleRate: 400 },
            { sensorKey: 11, sampleRate: 50 },
            { sensorKey: 26, sampleRate: 50 }
        ]
    };

    fixedConfigs[7] = {
        desc: 'ECG (requires plugin)',
        highSpeed: false,
        frequencies: [100, 200, 400],
        sensors: [
            { sensorKey: 10, sampleRate: 400 }
        ]
    };

    fixedConfigs[8] = {
        desc: 'Header 3V',
        highSpeed: false,
        frequencies: [100, 200],
        sensors: [
            { sensorKey: 12, sampleRate: 200 },
            { sensorKey: 13, sampleRate: 100 },
            { sensorKey: 21, sampleRate: 100 },
            { sensorKey: 22, sampleRate: 100 },
            { sensorKey: 23, sampleRate: 100 }
        ]
    };

    fixedConfigs[9] = {
        desc: 'Microphone',
        highSpeed: false,
        frequencies: [1200, 2400],
        sensors: [
            { sensorKey: 6, sampleRate: 2400 }
        ]
    };

    fixedConfigs[10] = {
        desc: 'Magnetic',
        highSpeed: false,
        frequencies: [100, 200, 400],
        sensors: [
            { sensorKey: 2, sampleRate: 80 },
            { sensorKey: 12, sampleRate: 400 }
        ]
    };  // 0x0A

    /* ----------- High speed --------- */
    fixedConfigs[32] = { // 0x20
        desc: 'Gyroscope (HS)',
        highSpeed: true,
        frequencies: [800],
        sensors: [
            { sensorKey: 3, sampleRate: 760 }
        ]
    };

    fixedConfigs[12] = {
        desc: 'Header 3V3',
        highSpeed: false,
        frequencies: [100, 200],
        sensors: [
            { sensorKey: 12, sampleRate: 200 },
            { sensorKey: 13, sampleRate: 100 },
            { sensorKey: 21, sampleRate: 100 },
            { sensorKey: 22, sampleRate: 100 },
            { sensorKey: 23, sampleRate: 100 }
        ]
    };   // 0x0C

    fixedConfigs[33] = { // 0x21
        desc: 'Accelerometer (HS)',
        highSpeed: true,
        frequencies: [800],
        sensors: [
            { sensorKey: 1, sampleRate: 800 }
        ]
    };

    fixedConfigs[34] = { // 0x22
        desc: 'Orientation (HS)',
        highSpeed: true,
        frequencies: [100, 200, 400],
        sensors: [
            { sensorKey: 1, sampleRate: 400 },
            { sensorKey: 2, sampleRate: 80 },
            { sensorKey: 3, sampleRate: 190 } // GPI to check !!!
        ]
    };

    fixedConfigs[35] = { // 0x23
        desc: 'Motion',
        highSpeed: true,
        frequencies: [100, 200],
        sensors: [
            { sensorKey: 1, sampleRate: 200 },
            { sensorKey: 3, sampleRate: 190 },
            { sensorKey: 8, sampleRate: 200 },
            { sensorKey: 9, sampleRate: 100 }
        ]
    };

    fixedConfigs[36] = { // 0x24
        desc: 'Sports',
        highSpeed: true,
        frequencies: [100, 200],
        sensors: [
            { sensorKey: 1, sampleRate: 200 },
            { sensorKey: 2, sampleRate: 80 },
            { sensorKey: 3, sampleRate: 190 },
            { sensorKey: 10, sampleRate: 200 }
        ]
    };

    fixedConfigs[37] = { // 0x25
        desc: 'Pendulum (HS)',
        highSpeed: true,
        frequencies: [100, 200],
        sensors: [
            { sensorKey: 1, sampleRate: 200 },
            { sensorKey: 3, sampleRate: 190 },
            { sensorKey: 8, sampleRate: 200 }
        ]
    };

    fixedConfigs[38] = { // 0x26
        desc: 'Kitchen Sink',
        highSpeed: true,
        frequencies: [100],
        sensors: [
            { sensorKey: 1, sampleRate: 100 },
            { sensorKey: 2, sampleRate: 80 },
            { sensorKey: 3, sampleRate: 95 },
            { sensorKey: 4, sampleRate: 100 },
            { sensorKey: 7, sampleRate: 100 },
            { sensorKey: 8, sampleRate: 100 },
            { sensorKey: 9, sampleRate: 100 },
            { sensorKey: 11, sampleRate: 100 },
            { sensorKey: 12, sampleRate: 100 },
            { sensorKey: 13, sampleRate: 100 },
            { sensorKey: 21, sampleRate: 100 },
        ]
    };

    fixedConfigs[39] = { // 0x27
        desc: 'Microphone (HS)',
        highSpeed: true,
        frequencies: [2400, 4800],
        sensors: [
            { sensorKey: 6, sampleRate: 4800 }
        ]
    };

    fixedConfigs[40] = { // 0x28
        desc: 'Ambient Light (HS)',
        highSpeed: true,
        frequencies: [2400, 4800],
        sensors: [
            { sensorKey: 7, sampleRate: 4800 }
        ]
    };

    fixedConfigs[41] = { // 0x29
        desc: 'Ambient Light & Accel (HS)',
        highSpeed: true,
        frequencies: [200, 400, 800],
        sensors: [
            { sensorKey: 1, sampleRate: 800 },
            { sensorKey: 7, sampleRate: 800 }
        ]
    };

    fixedConfigs[42] = { // 0x2A
        desc: 'Force Gauge & Accel (HS)',
        highSpeed: true,
        frequencies: [200, 400, 800],
        sensors: [
            { sensorKey: 1, sampleRate: 800 },
            { sensorKey: 8, sampleRate: 800 }
        ]
    };

    fixedConfigs[43] = { // 0x2B
        desc: 'Ambient Light & Micro (HS)',
        highSpeed: true,
        frequencies: [1200, 2400],
        sensors: [
            { sensorKey: 6, sampleRate: 2400 },
            { sensorKey: 7, sampleRate: 2400 }
        ]
    };

    fixedConfigs[44] = { // 0x2C
        desc: 'Electrocardiograph (HS)',
        highSpeed: true,
        frequencies: [200, 400, 800],
        sensors: [
            { sensorKey: 10, sampleRate: 800 }
        ]
    };

    fixedConfigs[45] = { // 0x2D
        desc: 'High Gain (HS)',
        highSpeed: true,
        frequencies: [2400, 4800],
        sensors: [
            { sensorKey: 12, sampleRate: 4800 }
        ]
    };

    fixedConfigs[46] = { // 0x2E
        desc: 'Force Gauge (HS)',
        highSpeed: true,
        frequencies: [2400, 4800],
        sensors: [
            { sensorKey: 8, sampleRate: 4800 }
        ]
    };

    fixedConfigs[47] = { // 0x2F (47)
        desc: 'ECG & Analog',
        highSpeed: true,
        frequencies: [100, 200, 400],
        sensors: [
            { sensorKey: 241, sampleRate: 400 } // 0xF1
        ]
    };

    /*********************************************************************
     *                  DO NOT MODIFY BELOW THIS LINE                    *
     *********************************************************************/

    function getDongleMode(code) {
        return dongleModes[code];
    }

    function getSensor(code) {
        return sensors[code];
    }

    function getFixedConfig(code) {
        return fixedConfigs[code];
    }

    function getFixedConfigs() {
        return fixedConfigs;
    }

    function getDefaultColor(arg) {
        var defaultColor = [colorRed, colorBlue, colorGreen];
        if (!arguments.length) {
            return defaultColor;
        }
        return defaultColor[arg % 3];
    }

    function getAreaUnit(unit) {
        if (!unit) {
            return '';
        }
        switch (unit) {
            case 'm/s': return 'm';
            case 'm/s²': return 'm/s';
            case 'rad/s': return 'rad';
        }
        return unit + 's';
    }

    function getSlopeUnit(unit) {
        if (!unit) {
            return '';
        }
        switch (unit) {
            case 'm/s': return 'm/s²';
            case 'm/s²': return 'm/s³';
            case 'rad/s': return 'rad/s²';
        }
        return unit + '/s';
    }

    /*
     * @param sensorKey, configKey
     * @returns {string}
     */
    function getSampleRate(sensorKey, configKey) {
        var fixedConfig = _.filter(fixedConfigs[configKey].sensors, { sensorKey: sensorKey })[0];
        return fixedConfig.sampleRate;
    }

    /*
     * Sensor array of {code, desc}
     * @returns {Array}
     */
    function getSensors() {
        var res = [];
        _.forEach(sensors, function(sensor) {
            var newEntry = {
                code: sensor.code,
                desc: sensor.desc
            };
            if (sensor.subCharts) {
                newEntry.subCharts = _.map(sensor.subCharts, function(chart, idx) {
                    return { desc: chart.desc, checked: true, coordinate: idx };
                });
            }
            res.push(newEntry);
        });
        return res;
    }

    /*
     * Sensor Config array of {configKey, sensorKey, highSpeed, sampleRate}
     * @returns {Array}
     */
    function getSensorConfigs() {
        var sensorConfigs = [];
        _.forEach(fixedConfigs, function (fixedConfig, configKey) {
            _.forEach(fixedConfig.sensors, function (sensor) {
                sensorConfigs.push({
                    configKey: parseInt(configKey, 10),
                    sensorKey: sensor.sensorKey,
                    highSpeed: fixedConfig.highSpeed,
                    sampleRate: sensor.sampleRate
                });
            });
        });
        return sensorConfigs;
    }

    // Return an array containing objects as {legend: 'a_x (m/s2)', color: '#BB0000'} for each components (eg: x, y, z).
    // This array is be used to show/hide chart lines
    function getTraceSettings(sensorType, coordinate) {
        var traceSettings = [];
        var sensor = sensors[sensorType];

        _.forEach(sensor.legends, function (item, idx) {
            if (coordinate !== undefined && idx !== coordinate) return;
            traceSettings.push({
                show: true,
                legend: item,
                color: sensor.pathColors ? sensor.pathColors[idx] : getDefaultColor(idx)
            });
        });

        return traceSettings;
    }

    return {
        getSensor: getSensor,
        getSensors: getSensors,
        getFixedConfig: getFixedConfig,
        getFixedConfigs: getFixedConfigs,
        getDongleMode: getDongleMode,
        getDefaultColor: getDefaultColor,
        getAreaUnit: getAreaUnit,
        getSlopeUnit: getSlopeUnit,
        getSampleRate: getSampleRate,
        getSensorConfigs: getSensorConfigs,
        getTraceSettings: getTraceSettings
    };
});
