// GrokCMCore
if (typeof(GrokCM) == 'undefined') {
    var GrokCM = {};
}
GrokCM.Core = function(symbolName) {
    this.symbolName = symbolName;
    this.grokSchemaVersion = '1.0'
    this.codec             = 'utf8';
    this.srcCodec          = 'UTF-8';
    this.grokHost          = 'grok.kizasi.jp/api';
    this.ovrHost           = 'cm.jp.overture.com';
    this.source            = 'kizasi_jp_kitt_cat_ctxt_test';
    this.config            = '2039279329';
    this.defaultCtxtId     = ['sensi001', 'sensi002', 'sensi003', 'sensi004'],
    this.defaultCat        = ['default_automotive', 'default_business', 'default_career',
                              'default_education','default_entertainment','default_fashion',
                              'default_finance', 'default_home', 'default_travel'];
    this.switchLimit       = 1.0;
    this.targetTextMax     = 200;
    this.tryLoadAdMaxCount = 200;
};
GrokCM.Core.prototype = {
    coreVersion: 1.0,
    zSr: undefined,
    grokSrc: undefined,
    ovrSrc: undefined,
    grokData: undefined,
    grokDataLoadStatus: false,
    getType: function(){
        return 'kz';
    },
    getAdMaxCount: function() {
        return 2;
    },
    targetText: '',
    getTargetText: function() {
        return '';
    },
    trace: false,
    setStatus: function(status) {
        this.status = status;
        if (this.trace) {
            if (typeof (console) != 'undefined') {
                console.log(this.status);
            } else {
                alert(this.status);
            }
        }
    },
    status: 'init',
    invoke: function() {
        this.setStatus('invoke');
        this.switchLogic();
    },
    switchLogic: function() {
        this.setStatus('switchLogic');
        if (this.getAdMaxCount() < 1) {
            this.zSr = [];
            this.showAds(this.zSr);
        } else if (Math.random() < this.switchLimit) {
            this.setStatus('switchLogic grok');
            this.analyzeContents();
        }else{
            this.setStatus('switchLogic ovr');
            this.grokData = undefined;
            this.switchAd();
        }
    },
    analyzeContents: function() {
        this.setStatus('analyze');
        var targetText = '', grokQuery = [], script;
        targetText = this.getTargetText();
        this.targetText = targetText.substring(0, Math.min(this.targetTextMax, targetText.length));

        grokQuery.push('Source=' + this.source);
        grokQuery.push('Config=' + this.config);
        grokQuery.push('Type=' + this.getType());
        grokQuery.push('TargetText=' + GrokCM.Util.kishEncode(this.targetText));
        grokQuery.push('UseKish=true');
        grokQuery.push('SchemaVersion=' + this.grokSchemaVersion);
        grokQuery.push('OutputCoding=' + this.codec);
        grokQuery.push('OutputFormat=jsonp');
        grokQuery.push('CallbackFunc=' + this.symbolName + '.setGrokData');

        this.grokSrc = 'http://' + this.grokHost + '/grokCM.py/?' + grokQuery.join('&');
        script = document.createElement('script');
        script.type = 'text/javascript';
        script.charset = this.srcCodec;
        script.src = this.grokSrc;
        this.grokDataLoadStatus = false;
        document.body.appendChild(script);
        setTimeout(GrokCM.Util.deligate(this, this.grokDataLoadTimeout), 5000);
    },
    setGrokData: function(grokData) {
        this.setStatus('setGrokData');
        this.grokDataLoadStatus = true;
        this.grokData = grokData || undefined;
        this.switchAd();
    },
    grokDataLoadTimeout: function() {
        if (!this.grokDataLoadStatus) {
        this.setStatus('grokDataLoadTimeout');
            this.grokData = undefined;
            this.switchAd();
        }
    },
    switchAd: function() {
        this.setStatus('switchAd');
        var ovrQuery = [], keys = [], keyQuery = '';
        if (typeof(this.grokData) == 'undefined') {
            this.setStatus('switchAd ovr default');

            ovrQuery.push('source=' + this.source);
            ovrQuery.push('config=' + this.config);
            ovrQuery.push('type=' + this.getType());
            ovrQuery.push('mkt=jp');
            ovrQuery.push('ctxtId=' + GrokCM.Util.randomChoice(this.defaultCtxtId));
            ovrQuery.push('keywordCharEnc=utf8');
            ovrQuery.push('outputCharEnc=' + this.codec);
            ovrQuery.push('maxCount=' + this.getAdMaxCount());
            ovrQuery.push('ctxtCat=' + GrokCM.Util.randomChoice(this.defaultCat));

            this.ovrSrc = 'http://' + this.ovrHost + '/js_flat_1_0/?' + ovrQuery.join('&');
            this.loadAdData();
        } else if (this.grokData.ResultSet.Result.Status == 'ng contents') {
            this.setStatus('switchAd ng');
            this.ovrSrc = '';
            this.ngAd();
        } else {
            this.setStatus('switchAd grok');
            keys = GrokCM.Util.map(this.grokData.ResultSet.Result.CtxtKeys, function(key){
                return encodeURIComponent(key);
            });
            keyQuery = '';
            if (0 < keys.length) {
                keyQuery ='ctxtKeywords=' + keys.join(',');
            }

            ovrQuery.push('config=' + this.config);
            ovrQuery.push('source=' + this.source);
            ovrQuery.push('type=' + this.grokData.ResultSet.Result.Type);
            ovrQuery.push('mkt=jp');
            ovrQuery.push('ctxtId=' + this.grokData.ResultSet.Result.CtxtId);

            if (keyQuery != '') {
                ovrQuery.push(keyQuery);
            }

            ovrQuery.push('keywordCharEnc=utf8');
            ovrQuery.push('outputCharEnc=' + this.codec);
            ovrQuery.push('maxCount=' + this.getAdMaxCount());
            ovrQuery.push('ctxtCat=' + GrokCM.Util.randomChoice(this.defaultCat));

            this.ovrSrc = 'http://' + this.ovrHost + '/js_flat_1_0/?' + ovrQuery.join('&');
            this.loadAdData();
        }
    },
    loadAdData: function() {
        this.setStatus('loadAdData');
        var iframe, iframeDocument, iframeWindow, html;
        try {
            iframe = document.createElement('iframe');
            iframe.style.width = '0px';
            iframe.style.height = '0px';
            iframe.style.border = '0px';
            iframe.style.borderStyle = 'hidden';
        } catch (e) {}
        document.body.appendChild(iframe);
        iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
        html  = '';
        html += '<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">';
        html += '<head>';
        html += '<meta http-equiv="Content-Type" content="text/html; charset=' + this.srcCodec + '" />';
        html += '<script type="text/javascript" src="' + this.ovrSrc + '" charset="' + this.srcCodec + '" ></script>';
        html += '</head>';
        html += '<body></body>';
        iframeDocument.open();
        iframeDocument.write(html);
        iframeDocument.close();
        iframeWindow = iframe.contentWindow;
        (function(grok) {
            grok.setStatus('loadAdClosure');
            var timer = null, tryCount = 0;
            return function(){
                timer = setInterval(function() {
                    if (tryCount > grok.tryLoadAdMaxCount) {
                        grok.setStatus('loadAd timeOut tryCount:' + tryCount);
                        clearInterval(timer);
                        grok.loadAdDataTimeOut();
                    } else if (typeof(iframeWindow.zSr) == 'undefined') {
                        tryCount++;
                    } else if (iframeWindow.zSr.length > 0) {
                        grok.setStatus('adData loaded, tryCount:' + tryCount);
                        clearInterval(timer);
                        grok.zSr = [];
                        for (var i = 0, len = iframeWindow.zSr.length ;i < len;i++) {
                            grok.zSr[i] = iframeWindow.zSr[i];
                        }
                        grok.showAds(grok.zSr);
                    } else {
                        tryCount++;
                    }
                }, 100);
            };
        })(this)();
    },
    showAds: function(adData) {
        //
    },
    ngAd: function() {
        this.grokData = undefined;
        this.switchAd();
    },
    loadAdDataTimeOut: function() {
        //
    }
};

GrokCM.Util = {
    deligate: function(target, func) {
        return function() {
            func.apply(target, arguments);
        }
    },
    randomChoice: function(args) {
        return args[Math.floor(Math.random() * args.length)];
    },
    textWrap: (function() {
        if (/opera/.test(navigator.userAgent.toLowerCase())) {
            return function(str) {
                return String(str).replace(/(.)/g, '$1' + '&#8203;');
            };
        } else {
            return function(str) {
                return String(str).replace(/(.)/g, '$1' + '<wbr />');
            };
        }
    })(),
    strip: function(str) {
        return String(str).replace(/^[ \s]*/gim, '').replace(/[ \s]*$/gim, '');
    },
    getText: function(node) {
        var targetNode = node || document.body;
        var children = targetNode.childNodes, texts = [];
        for (var child, type, nodeName, i=0, len = children.length;i < len; i++) {
            child = children.item(i);
            type = child.nodeType;
            if (type == 1) {
                // Element Node
                nodeName = child.nodeName;
                if ((nodeName != 'SCRIPT')&&(nodeName != 'NOSCRIPT')) {
                    texts.push(arguments.callee(child));
                }
            } else if (type == 3) {
                // Text Node
                texts.push(child.data);
            } else if (type == 8) {
                // Comment Node
            }
        }
        return texts.join('');
    },
    getTextByMark: function(startMark, endMark, node) {
        var html, startIndex, endIndex, targetText = '', targetNode = node || document.body;
        html = targetNode.innerHTML;
        startIndex = startMark.length + html.indexOf(startMark);
        endIndex = html.indexOf(endMark);
        if (startIndex < endIndex) {
            targetText = this.strip(html.substring(startIndex, endIndex)).replace(/<\/?[^>]+>/gi, '');
        }
        return targetText;
    },
    getElementsByClassName: function(className, node) {
        var targetNode = node || document;
        var children = targetNode.getElementsByTagName('*') || document.all;
        var elements = [];
        for (var i = 0, len1 = children.length; i < len1; i++) {
            var classNames = children[i].className.split(' ');
            for (var j = 0, len2 = classNames.length; j < len2; j++) {
                if (classNames[j] == className) {
                    elements.push(children[i]);
                    break;
                }
            }
        }
        return elements;
    },
    map: function(args, func) {
        var results = [];
        for (var i = 0, len = args.length; i < len; i++) {
            results.push(func(args[i]));
        }
        return results;
    },
    addListener: (function() {
        if ( window.addEventListener ) {
            return function(node, type, func) {
                node.addEventListener(type, func, false);
            }
        } else if ( window.attachEvent ) {
            return function(node, type, func) {
                var wrapperFunc = function() {
                    func.call(node, window.event);
                };
                node.attachEvent('on'+type, wrapperFunc);
            };
        } else {
            return function(node, type, func) {
                node['on'+type] = func;
            }
        }
    })(),
    kishEncode: function(targetStr) {
        if (targetStr == '') {
            return '';
        }
        var encstr = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789()'.split('');
        var chrcode, bitcnt, rest;
        chrcode = bitcnt = rest = 0;
        for (var i = 0, len = targetStr.length, result = ''; i < len; i++) {
            chrcode = targetStr.charCodeAt(i);
            rest <<= 16;
            rest |= chrcode;
            bitcnt += 16;
            while (bitcnt >= 6) {
                result += encstr[rest >> (bitcnt - 6)];
                rest &= (1 << (bitcnt - 6)) - 1;
                bitcnt -= 6;
            }
        }
        if (bitcnt) {
            result += encstr[rest << (6 - bitcnt)];
        }
        return result;
    }
};
