var ajax, filesys, tdb;

/*global window: false */
ajax = (function () {
    "use strict";
    var hName = 'Content-Type',
        hValue = 'application/x-www-form-urlencoded';

    return {
        post: function (url, msg) {
            var xhr = new XMLHttpRequest();
            xhr.open("POST", url, false);
            xhr.setRequestHeader(hName, hValue);
            xhr.send(msg);
            return xhr.responseText;
        }
    };
}());

filesys = (function () {
    "use strict";
    var xfso, adsi, nl = '\r\n', sep = '\t',
        ForReading = 1, ForWriting = 2, ForAppending = 8;

    function getParent(f) { return xfso.GetParentFolderName(f).substring(1); }
    function combine(path, more) { return path + "/" + more; }
    function exists(path) { return xfso.FolderExists(path); }
    function create(path) { xfso.CreateFolder(path); }
    function remove(path) { xfso.DeleteFolder(path); }
    function unFile(path) { xfso.DeleteFile(path); }
    function getFiles(path) { return xfso.GetFolder(path).Files; }
    function getExt(path) { return xfso.GetExtensionName(path); }

    function append(file, data) {
        var tf = xfso.OpenTextFile(file, ForAppending, true);
        tf.WriteLine(data);
        tf.Close();
    }
    function writeAll(file, data) {
        var tf = xfso.OpenTextFile(file, ForWriting, true);
        tf.Write(data);
        tf.Close();
    }

    function readAll(file) {
        var data, tf = xfso.OpenTextFile(file, ForReading, true);
        data = tf.ReadAll();
        tf.Close();
        return data;
    }

    function find_Lock(file, row) {
        var a, d, data;
        data = readAll(file);
        data = data.split(nl);
        for (d = 0; d < data.length; d = d + 1) {
            a = data[d].split(sep);
            if (+a[0] === +row) { return a[1]; }  // row found
        }
        return -1;                                // row not found
    }

    function lock(file, user, row) {
        var lok, d, t = new Date();
        try {lok = find_Lock(file, row); 
            } catch (e) {lok = -1; }
        if (lok < 0) {
            d = row + sep + user + sep + t.getTime();
            append(file, d);
            lok = find_Lock(file, row);   // in case of conflict
        }
        return lok === user;
    }

    function free(file, user, row) {
        var a, d, data;
        data = readAll(file);
        data = data.split(nl);
        for (d = 0; d < data.length; d = d + 1) {
            a = data[d].split(sep);
            if (a[1] === user) {
                if (a[0] === row || row === '*') {
                    data.splice(d, 1);
                    d = d - 1;
                }
            }
        }
        data = data.join(nl);
        writeAll(file, data);
    }

    return {
        post: function (msg) {
            var en, f, files, file1, file2, data = "OK",
                sheet = msg['sheet'], row = msg['row'], range = msg['range'],
                user = msg['user'] || 'dcw',
//                user = msg['user'] || adsi.UserName,
                path = getParent(window.location.pathname);
            path = combine(path, "./db");
            path = combine(path, msg['book']);
            file1 = combine(path, sheet + '.tdb');
            file2 = combine(path, sheet + '.lok');
            row = (row === undefined) ? -1 : +row;
            range = (range === undefined) ? -1 : +range;
            try {
                switch (msg['action']) {
                case 'append':
                    append(file1, msg['data']);
                    break;
                case 'load':
                    data = readAll(file1);
                    if (row > 0 || range > 0) {
                        data = data.split(nl);
                        if (row < 0) {row = 0; }
                        if (range < 1) {range = data.length; }
                        data = data.slice(row, row + range);
                        data = data.join(nl); 
                    }
                    break;
                case 'read':
                    data = readAll(file1);
                    data = data.split(nl);
                    data = data[row];
                    break;
                case 'next':
                    data = readAll(file1);
                    data = data.split(nl);
                    data = data.length - 1;
                    break;
                case 'lock':
                    data = lock(file2, user, row);
                    break;
                case 'unlock':
                    free(file2, user, row);
                    break;
                case 'write':
                    if (lock(file2, user, row)) {
                        data = readAll(file1);
                        data = data.split(nl);
                        data[row] =  msg['data'];
                        data = data.join(nl);
                        writeAll(file1, data);
                    } else {
                        data = 'no action';
                    }
                    break;
                case 'create':
                    if (!exists(path)) {create(path); }
                    break;
                case 'remove':
                    if (exists(path)) {remove(path); }
                    break;
                case 'freeAll':
                    files = getFiles(path);
                    en = new Enumerator(files);
                    for (en; !en.atEnd(); en.moveNext()) {
                        f = en.item();
                        if (getExt(f) === 'lok') {
                            unFile(f);
                        }
                    }
                    break;
                case 'free':
                    files = getFiles(path);
                    en = new Enumerator(files);
                    for (en; !en.atEnd(); en.moveNext()) {
                        f = en.item();
                        if (getExt(f) === 'lok') {
                            free(f, user, '*');
                        }
                    }
                    break;
                default:
                    data = 'no action';
                    break;
                }
            } catch (e) {
                data = "Error: " + e.message;
            }
            return data;
        },

        init: function () {
            xfso = new ActiveXObject("Scripting.FileSystemObject");
            adsi = new ActiveXObject("ADSystemInfo");
        }
    };
}());

tdb = (function () {
    "use strict";
    var mode, dbURL = "./tdb.ashx";

    function reMsg(msg) {
        var str = 'action=' + msg.action;
        str = str + '&book=' + msg.book;
        if (msg.sheet) {str = str + '&sheet=' + msg.sheet; }
        if (msg.row > -1) {str = str + '&row=' + msg.row; }
        if (msg.range > -1) {str = str + '&row=' + msg.range; }
        if (msg.data) {str = str + '&data=' + msg.data; }
        if (msg.user) {str = str + '&user=' + msg.user; }
        return str;
    }

    return {
        init: function () {
            mode = window.location.protocol;
            if (mode === 'file:') {filesys.init(); }
        },

        post: function (msg) {
            var data, rem = reMsg(msg);
            if (mode === 'http:') {
                data = ajax.post(dbURL, rem);
            } else {data = filesys.post(msg); }
            return data;
        }
    };
}());

