/*global requirejs, data, VLE*/
require(
    ['../main'],
    function () {
        "use strict";
        require(
            [
                'utils',
                'loader',
                'inline',
                'buttons',
                'feedback'
            ],
            function (utils, ldr, inline, buttons, feedback) {
                var type = 'inline',
                    loader;

                var init = function() {
                    var index = '',
                        url, data;

                    if (VLE.serverversion) {
                        url = VLE.get_param('settings'); // VLE attachment name for JSON file
                        data = {};

                        if (url.split('.').pop() == 'json') {
                            data.file = [url];
                        }
                        else {
                            data.folder = ['settings'];
                        }

                        load(data, 0);
                    }
                    else { //local testing
                        require(['inline-data'], function(data) {
                            if (typeof index == 'number') {
                                load(data.examples[index], 0);
                            }
                            else {
                                data.examples.forEach(function(data, i) {
                                    load(data, i);
                                });
                            }
                        });
                    }
                };

                var load = function(data, index) {
                    var id = type + '-activity' + index,
                        container = document.body.appendChild(utils.createElement('div', 'container', id));

                    loader = ldr.construct();

                    if (VLE.serverversion) {
                        loader.load({
                            container: container,
                            load: data,
                            callback: function(data) {
                                create(data.file[0], container, id);
                            }
                        });
                    }
                    else {
                        data.images = data.images || {};
                        data.images.dir = 'img/';
                        data.images.files = data.images.files || [];

                        if (data.backgroundImage) {
                            data.images.files.push(data.backgroundImage);
                        }

                        loader.load({
                            container: container,
                            dir: data.images.dir,
                            load: {
                                image: data.images.files
                            },
                            callback: function() {
                                create(data, container, id);
                            }
                        });
                    }
                };

                var create = function(data, container, id) {
                    var activity, btnGroup, fb;

                    if (typeof data.css != 'undefined') {
                        addCSS(data.css, id);
                    }

                    //support for old data files
                    if (Array.isArray(data.answer)) {
                        data.answer = {
                            data: data.answer
                        };
                    }

                    activity = inline(data, container);

                    if (!container.contains(activity.container)) {
                        container.appendChild(activity.container);
                    }

                    //TODO still got a timing issue here when calculating the total no. of answers!!!
                    //the following needs to run after the core activity has completely loaded - trigger event.
                    if (data.buttons) {
                        if (!activity.cfg.answer.overlay) {
                            utils.extendDeep(data.buttons, {
                                data: {
                                    reveal: {
                                        html: 'Reveal answer'
                                    }
                                }
                            });
                        }

                        btnGroup = buttons.construct(data.buttons);
                        container.appendChild(btnGroup.group);

                        if (btnGroup.active('check')) {
                            data.feedback = data.feedback || {};

                            utils.extendDeep(data.feedback, {
                                alternates: true
                            });

                            fb = feedback.construct(data.feedback, container, btnGroup);
                            container.appendChild(fb.el);
                        }
                    }

                    utils.triggerCustomEvent(container, 'activity-loaded');
                    container.style.visibility = 'visible';
                    //VLE.resize_iframe();

                    console.log(JSON.stringify(data));
                };

                var addCSS = function(css, id) {
                    var el, ss;

                    if (typeof css == 'string') {
                        el = document.head.appendChild(document.createElement('link'));
                        el.rel = 'stylesheet';
                        el.href = css;
                    }
                    else {
                        el = document.head.appendChild(document.createElement('style'));
                        //ss = document.head.styleSheets[document.head.styleSheets.length - 1];
                        ss = el.sheet;

                        utils.forIn(css, function (rules, selector) {
                            rules = Array.isArray(rules) ? rules : [rules];

                            rules.forEach(function (rule) {
                                ss.insertRule('#' + id + ' ' + selector + '{' + rule + '}', ss.cssRules.length);
                                console.log(ss);
                            });
                        });
                    }
                };

                init();
            }
        );
    }
);
define("activities/inline_activity", function(){});

define(
    'inline',[
        'utils',
        'loader',
        'saver',
        'input'
    ],
    function (utils, loader, saver, input) {
        "use strict";

        return function inline(data, parent) {
            if (!data.html) {
                throw new Error('No question data supplied');
            }

            var dom = {
                parent: parent || document.getElementsByTagName('body')[0],
                container: utils.createElement('div', 'inline-container'),
                question: utils.createElement('div', 'question'),
                answer: null,
                inputs: []
            };

            var cfg = {
                type: 'text',
                theme: '',
                width: 512,
                classes: [],
                intro: '',
                html: '',
                lang: 'en',
                placeholder: {
                    start: '[[',
                    end: ']]',
                    delimeter: '|',
                    index: {
                        enabled: false,
                        zeroBased: true
                    }
                },
                inputs: {
                    data: [], //store data for input objects here
                    text: {
                        width: 'auto',
                        resize: false
                    },
                    select: {
                        options: [], //holds option arrays that can be referenced by placeholder start/end and index
                        shuffle: [] //true for global or index of select to shuffle options
                    }
                },
                footnote: '',
                answer: {
                    data: [],
                    overlay: true
                },
                showCorrect: false,
                showIncorrect: false,
                resetConfirm: false
            };

            var answer = null,
                attempt = null;

            var setCfg = function() {
                if (data.type == 'text') {
                    cfg.answer.overlay = false;
                }

                utils.extendDeep(cfg, data);
            };

            var init = function(dataLoaded) {
                initQuestion();
                initInputs();
                setEventHandlers();

                if (dataLoaded) {
                    toggle(true);
                }

                if (cfg.answer.data.length === 0) {
                    getAnswer();
                }

                if (!cfg.answer.overlay) {
                    toggle();
                    disableInputs();
                    dom.answer = dom.question.cloneNode(true);
                    dom.answer.className = 'inline-answer';
                    toggle(true);
                    enableInputs();
                }

                dom.parent.addEventListener('check', submit);
                dom.parent.addEventListener('reveal', reveal);
                dom.parent.addEventListener('reset', reset);
                dom.parent.addEventListener('retry', retry);
                dom.parent.addEventListener('max-attempts-reached', toggle);
            };

            var initQuestion = function() {
                var start = utils.escapeRegExp(cfg.placeholder.start),
                    end = utils.escapeRegExp(cfg.placeholder.end),
                    re = new RegExp(start + '(.*?)' + end, 'g'),
                    index = 0;

                dom.question.lang = cfg.lang;

                if (cfg.intro) {
                    dom.question.insertAdjacentHTML('beforeend', '<div class="dnd-intro">' + cfg.intro + '</div>');
                }

                cfg.html = cfg.html.replace(re, function(match) {
                    if (!cfg.inputs.data[index]) {
                        setInputData(match, index);
                    }
                    index++;

                    //replace with something we can query...
                    return '<span class="inline-input"></span>';
                });

                dom.question.insertAdjacentHTML('beforeend', cfg.html);

                if (cfg.footnote) {
                    dom.question.insertAdjacentHTML('beforeend', '<div class="dnd-footnote">' + cfg.footnote + '</div>');
                }

                dom.container.appendChild(dom.question);
            };

            //TODO refactor/break it down...
            var setInputData = function(str, index) {
                var data = {
                    type: cfg.type,
                    label: {
                        prefix: 'input ' + (index + 1)
                    }
                };
                var answer = cfg.answer.data,
                    num, array;

                str = str.replace(cfg.placeholder.start, '').replace(cfg.placeholder.end, '');

                if (cfg.placeholder.index.enabled) {
                    num = cfg.placeholder.index.zeroBased ? parseInt(str, 10) : parseInt(str, 10) - 1;

                    switch (cfg.type) {
                        case 'select':
                            data.options = cfg.inputs.select.options[num].map(function(str) { return { label: str }; });
                            data.shuffle = (cfg.inputs.select.shuffle.indexOf(num) > -1);
                            data.answer = answer[index] || 0;
                            break;
                        case 'text':
                            answer[num] = Array.isArray(answer[num]) ? answer[num] : [answer[num]];

                            answer[num].forEach(function(str, i, arr) {
                                if (/[\u2018\u2019]/.test(str)) {
                                    arr.push(str.replace(/[\u2018\u2019]/g, '\''));
                                }

                                arr[i] = str.trim();
                            });

                            data.answer = answer[num];
                    }
                }
                else {
                    array = str.split(cfg.placeholder.delimeter);

                    array.forEach(function(str, i, arr) {
                        arr[i] = str.trim();
                    });

                    switch (cfg.type) {
                        case 'select':
                            data.options = array.map(function(str) { return { label: str }; });
                            data.shuffle = (cfg.inputs.select.shuffle === true) || (cfg.inputs.select.shuffle.indexOf(index) > -1);
                            data.answer = answer[index] || 0;
                            break;
                        case 'text':
                            array.forEach(function(str, i, arr) {
                                if (/[\u2018\u2019]/.test(str)) {
                                    arr.push(str.replace(/[\u2018\u2019]/g, '\''));
                                }
                            });

                            data.answer = array;
                    }
                }

                cfg.inputs.data.push(data);
            };

            var initInputs = function() {
                var label, data;

                utils.toArray(dom.question.querySelectorAll('.inline-input'))
                    .forEach(function(placeholder, i) {
                        data = cfg.inputs.data[i];
                        label = input.create(data);
                        label.className = 'inline-' + data.type;
                        data.el.setAttribute('data-input-index', i.toString());
                        dom.inputs.push(data.el);
                        utils.addClass(label.firstChild, 'screen-reader');
                        placeholder.parentNode.replaceChild(label, placeholder);
                    });

                if (cfg.type == 'text') {
                    resizeTextInputs();
                }
            };

            var resizeTextInputs = function() {
                var span = dom.parent.appendChild(document.createElement('span')),
                    max = 0, width;

                cfg.inputs.data.forEach(function(data) {
                    width = 0;

                    data.answer.forEach(function(answer) {
                        span.textContent = answer;

                        if (span.offsetWidth > width) {
                            width = span.offsetWidth;
                        }

                        if (width > max) {
                            max = width;
                        }
                    });

                    if (typeof data.width != 'number' && typeof cfg.inputs.text.width != 'number') {
                        data.width = width;
                    }
                });

                dom.parent.removeChild(span);

                if (typeof cfg.inputs.text.width != 'number') {
                    cfg.inputs.text.width = max;
                }

                dom.inputs.forEach(function (input, i) {
                    width = cfg.inputs.text.resize ? cfg.inputs.text.width : (cfg.inputs.data[i].width || cfg.inputs.text.width);
                    input.style.width = width + 10 + 'px';
                });
            };

            var change = function(e) {
                var data, index;

                index = e.target.getAttribute('data-input-index');
                data = cfg.inputs.data[index];

                switch (data.type) {
                    case 'text':
                        data.attempt = e.target.value;
                        break;
                    case 'select':
                        data.attempt = parseInt(e.target.value, 10);
                }
            };

            var setEventHandlers = function() {
                dom.question.addEventListener('change', change);
            };

            var getAnswer = function() {
                cfg.inputs.data.forEach(function(data) {
                    cfg.answer.data.push(data.answer);
                });

                console.log(cfg.answer.data);
            };

            var getAttempt = function() {
                attempt = [];

                cfg.inputs.data.forEach(function(data) {
                    attempt.push(data.attempt);
                });
            };

            var submit = function() {
                disableInputs();
                getAttempt();

                utils.triggerCustomEvent(dom.parent, 'feedback', {
                    attempt: attempt,
                    answer: cfg.answer.data
                });

                console.log(cfg.answer.data, attempt);
            };

            var reveal = function(e) {
                if (cfg.answer.overlay) {
                    if (e.detail.pressed) {
                        toggle();
                        disableInputs();
                    }
                    else {
                        toggle(true);
                        enableInputs();
                    }
                }
                else {
                    disableInputs();
                    dom.parent.appendChild(dom.answer);
                    VLE.resize_iframe();
                }
            };

            var toggle = function(attempt) {
                var answer = attempt ? 'attempt' : 'answer',
                    index;

                cfg.inputs.data.forEach(function(data, i) {
                    switch (data.type) {
                        case 'text':
                            index = (typeof cfg.answer.data[i] == 'number') ? cfg.answer.data[i] : 0;
                            dom.inputs[i].value = (attempt ? data[answer] : data[answer][index]) || '';
                            break;
                        case 'select':
                            index = 0;

                            //TODO better way??
                            if (typeof data[answer] == 'number') {
                                Array.prototype.some.call(dom.inputs[i].children, function(el, i) {
                                    if (el.value == data[answer]) {
                                        index = i;
                                        return true;
                                    }
                                });
                            }

                            dom.inputs[i].selectedIndex = index;
                    }
                });
            };

            var enableInputs = function() {
                dom.inputs.forEach(function(input) {
                    input.removeAttribute('disabled');
                });
            };

            var disableInputs = function() {
                dom.inputs.forEach(function(input) {
                    input.disabled = true;
                });
            };

            var reset = function() {
                if (cfg.resetConfirm && !window.confirm('Resetting the activity will clear all saved data.')) {
                    return false;
                }

                cfg.inputs.data.forEach(function(data, i) {
                    delete data.attempt;

                    switch (cfg.type) {
                        case 'select':
                            dom.inputs[i].selectedIndex = 0;
                            break;
                        case 'text':
                            dom.inputs[i].value = data.value || '';
                    }
                });

                enableInputs();

                if (cfg.answer.overlay) {
                    toggle(true);
                }
                else {
                    if (dom.parent.contains(dom.answer)) {
                        dom.parent.removeChild(dom.answer);
                        VLE.resize_iframe();
                    }
                }
            };

            var retrieveData = function(callback) {
                saver.retrieve({
                    names: getSaveObj(),
                    callback: function(obj) {
                        var dataLoaded = false;

                        if (obj.data !== '') {
                            dataLoaded = true;
                            cfg.inputs.data = JSON.parse(obj.data);
                        }

                        callback(dataLoaded);
                    }
                });
            };

            var getSaveObj = function() {
                var obj = {};

                obj.data = JSON.stringify(cfg.inputs.data);

                return obj;
            };

            var save = function() {
                saver.save({
                    values: getSaveObj()
                });
            };

            var retry = function() {
                enableInputs();
            };

            setCfg();
            retrieveData(init);

            return {
                container: dom.container,
                dom: dom,
                cfg: cfg
            };
        };
    });
