/*
 * /js/cosme.js
 * /js/dojo/dojo.js 依存
 */

(function () {
    if (typeof cosmes == 'undefined') {
        this.cosmes = {
            '_scopeName' : 'cosmes'
        };
    }

    if (typeof cosme == 'undefined') {
        this.cosme = {
            'autoload' : [],
            'onload' : [],
            'preload' : [],
            'global' : this,
            'parameters'  : {},
            '_scopeName' : 'cosme',
            '_loaded' : {},
            '_parameters'  : {},
            '_services'  : this.cosmes
        };
    }
})();

/*
 * 初期化と破棄
 */

cosme.initialize = function () {
    if (dojo.isMozilla) {
        window.addEventListener('load', function (e) { window.event = e; }, true);
        window.addEventListener('click', function (e) { window.event = e; }, true);
        window.addEventListener('submit', function (e) { window.event = e; }, true);
        window.addEventListener('mouseup', function (e) { window.event = e; }, true);
        window.addEventListener('mousedown', function (e) { window.event = e; }, true);
        window.addEventListener('mousemove', function (e) { window.event = e; }, true);
        window.addEventListener('mouseover', function (e) { window.event = e; }, true);
        window.addEventListener('mouseout', function (e) { window.event = e; }, true);
        window.addEventListener('scroll', function (e) { window.event = e; }, true);
        window.addEventListener('keyup', function (e) { window.event = e; }, true);
        window.addEventListener('keydown', function (e) { window.event = e; }, true);
        window.addEventListener('keypress', function (e) { window.event = e; }, true);
    }
    try { cosme._autoloader(); } catch (e) { }
    //try { cosme._onloader(); } catch (e) { }
    cosme._onloader();
};
cosme.destructor = function () {
};

/*
 * 基幹
 */

cosme.addOnLoad = function (methodName) {
    return dojo.addOnLoad(methodName);
};
cosme.addOnUnload = function (methodName) {
    return dojo.addOnUnload(methodName);
};
cosme.provide = function (moduleName) {
    return dojo.provide(moduleName);
};
cosme.require = function (moduleName) {
    return dojo.require(moduleName);
};
cosme.request = function (url, options) {
    options = options || {
        // form           : フォーム要素(DOM)
        // handle         : ハンドル？
        // handleAs       : ハンドルエイリアス？
        // method         : リクエストメソッド,
        // parameters     : パラメータ,
        // postBody       : リクエストボディ,
        // requestHeaders : リクエストヘッダ,
        // asynchronous   : 非同期通信フラグ,
        // preventCache   : キャッシュフラグ,
        // contentType    : コンテントタイプ（未実装）,
        // onCreate       : オブジェクト作成時の処理（未実装）,
        // onLoading      : 読み込み開始時の処理（未実装）,
        // onLoaded       : 読み込み終了時の処理（未実装）,
        // onSuccess      : 読み込み成功時の処理（未実装）,
        // onFailure      : 通信失敗時の処理,
        // onComplete     : 通信完了時の処理,
        // onCallback     : 処理完了後の処理
        // onException    : 例外処理（未実装）,
    };

    if (typeof url === 'undefined')
        throw new Error('urlが設定されていません。');

    if (typeof options.onComplete !== 'function')
        throw new Error('onComleteがfunctionではありません。');

    // postBody
    if (options.postBody) {
        options.method = 'post';
        options.parameters += (options.parameters ? '&' : '') + options.postBody
    } else {
        options.method = options.method || 'get';
    }

    // requestHeaders
    options.requestHeaders = options.requestHeaders || {};

    // requestHeaders.X-Cosme-Content-Type
    options.requestHeaders['X-Cosme-Content-Type'] =
        options.requestHeaders['X-Cosme-Content-Type'] || '';

    // requestHeaders.X-Cosme-Charset
    options.requestHeaders['X-Cosme-Charset'] =
        options.requestHeaders['X-Cosme-Charset'] || 'Shift_JIS';

    var deferred = dojo.xhr(
        options.method, {
            content : options.parameters,
            error : options.onFailure,
            form : options.form,
            handle : options.handle,
            handleAs : options.handleAs,
            headers : options.requestHeaders,
            load : options.onComplete,
            preventCache : options.preventCache,
            sync : (options.asynchronous == null) ? false : !options.asynchronous,
            timeout : null,
            url : url
        },
        (options.method.toLowerCase() === 'post') ? true : false);

    deferred.addCallback(options.onCallback);
    deferred.addErrback(options.onException);

    return deferred;
};
cosme.fromJson = function (string) {
    return dojo.fromJson(string);
};
cosme.setConfig = function (key, config) {
    this[key] = config;
};
cosme.coords = function (elem) {
    var coords = dojo.coords(elem);

    if (dojo.isIE <= 7 && elem.offsetParent) {
        coords.t += dojo.style(elem.offsetParent, 'marginTop');
        coords.l += dojo.style(elem.offsetParent, 'marginLeft');
    }

    return coords;
};

/*
 * update系
 */

cosme.update = function (node, options) {
    this.event.stop();

    node = (node && node.tagName) ? node : this.getNode(node);
    options = options || { /* cosme.request() 参照 */ };

    if (typeof node === 'undefined')
        throw new Error('nodeが指定されていません。');

    var url = options.url
        || this.event.target().getAttribute('url', 2)
        || this.event.target().getAttribute('href', 2);

    if (typeof url === 'undefined')
        throw new Error('urlが設定されていません。');

    if (!options.parameters) {
        var _params = this.event.target().getAttribute('parameters');
        options.parameters = (!!_params) ? this.fromJson('{' + _params + '}') : null;
    }

    if (!options.onComplete) {
        options.onComplete = function (data, xhr) { node.innerHTML = data; }; }

    options.preventCache = (options.preventCache == null) ? true : options.preventCache;

    var deferred = this.request(url, options);
};
cosme.updateId = function (id, options) {
    this.update(this.getNodeById(id), options)
};
cosme.updateSelector = function (selector, options) {
    this.update(this.getNodesBySelector(selector)[0], options);
};

/*
 * DOM系
 */

cosme.node = function (node) {
    if (this._loaded['node'] == null) {
        this.require('cosme.Node');
        this._loaded['node'] = new cosme.Node({ node : node });
    }

    if (node)
        this._loaded['node'].setNode(node);

    return this._loaded['node'];
};
cosme.getNode = function (_node, parent) {
    var node = this.getNodeById(_node, parent);
    return (!!node) ? node : this.getNodesBySelector(_node)[0];
};
cosme.getNodeById = function (id, parent) {
    return dojo.byId(id, parent);
};
cosme.getElementById = function (id, parent) {
    return this.getNodeById(id, parent);
};
cosme.getNodes = function (selector, parent) {
    return this.getNodesBySelector(selector, parent);
};
cosme.getNodesBySelector = function (selector, parent) {
    return dojo.query(selector, parent)
};
cosme.getElementsBySelector = function (selector, parent) {
    return this.getNodesBySelector(selector, parent)
};

/*
 * ecl
 */

cosme.ecl = function () {
    cosme.require('cosme._ecl');
    return this._ecl;
};

/*
 * location系
 * 使わなそうだなーと思いつつ
 */

cosme.location = {
    href : function (href) {
        location.href = href;
    }
};

/*
 * event系
 */

cosme.event = {
    get : function (key) {
        return (key) ? dojo.fixEvent(window.event)[key] : dojo.fixEvent(window.event);
    },
    target : function () {
        return this.get().target;
    },
    stop : function () {
        dojo.stopEvent(this.get());
    }
};

/*
 * window系
 */

cosme.window = {
    'innerWidth' : function () {
        return document.body.clientWidth
            || document.documentElement.clientWidth
            || window.innerWidth
            || 0;
    },
    'innerHeight' : function () {
        return document.body.clientHeight
            || document.documentElement.clientHeight
            || window.innerHeight
            || 0;
    },
    'scrollTop' : function () {
        return document.body.scrollTop
            || document.documentElement.scrollTop
            || window.pageYOffset
            || 0;
    },
    'scrollLeft' : function () {
        return document.body.scrollLeft
            || document.documentElement.scrollLeft
            || window.pageXOffset
            || 0;
    }
};

/*
 * private
 */

cosme._autoloader = function () {
    for (var i = 0; i < arguments.length; ++i) {
        if (arguments[i])
            this.require(arguments[i]);
    }

    if (!this.autoload)
        return;

    if (typeof this.autoload === 'string')
        this.autoload = [this.autoload];

    for (var i = 0; i < this.autoload.length; ++i) {
        if (this.autoload[i])
            this.require(this._services._scopeName + '.' + this.autoload[i]);
    }
};
cosme._onloader = function () {
    if (!this.onload)
        return;

    if (typeof this.onload === 'string')
        this.onload = [this.onload];

    ONLOADER: for (var j = 0; j < this.onload.length; ++j) {
        var obj = this.global[this._services._scopeName];
        var scopes = this.onload[j].split('.');
        for (var i = 0; i < scopes.length; ++i) {
            if (obj[scopes[i]])
                obj = obj[scopes[i]];
            else
                continue ONLOADER;
        }
        try {
            obj(cosme.parameters);
        }
        catch (e) {
            console.log('error');
            console.log(e);
        }
    }
};

cosme._preloader = function () {
    if (!this.preload)
        return;

    if (typeof this.preload === 'string')
        this.preload = [this.preload];

    for (var i = 0; i < this.preload.length; i++) {
        this.require(this._services._scopeName + '.' + this.preload[i]);
    }
};

(function () {
    var cosmeScript = cosme.getNode('script[cosmeConfig]');
    var configString = cosmeScript.getAttribute('cosmeConfig');
    var paramsString = cosmeScript.getAttribute('cosmeParameter');

    var cosmeConfig = cosme.fromJson('{' + configString + '}');
    cosme.parameters = cosme.fromJson(paramsString || '{}');

    for (key in cosmeConfig)
        cosme.setConfig(key, cosmeConfig[key]);

    // 指定が無い場合はタイムスタンプを使う
    if (cosmeConfig['cacheBust'] == null) {
        dojo.config.cacheBust = (new Date()).getTime();
    } else {
        dojo.config.cacheBust = cosmeConfig['cacheBust'];
    }

    cosme._preloader();

    cosme.addOnLoad(cosme.initialize);
    cosme.addOnUnload(cosme.destructor);
})();
