if (typeof Mogel == 'undefined') {
    Mogel = {};
}

//star rate
Mogel.StarRate = function() {
    this._star = new Array();
}
Mogel.StarRate.prototype = {
    add: function(star) {
        this._star.push({obj: star, flg: true});
    },
    _mode: function(star, bool) {
        var len = this._star.length;
        for (var i=0; i<len; i++) {
            if (this._star[i].obj == star) {
                this._star[i].flg = bool;
                star.className = bool ? 'enable' : 'disable';
            }
        }
    },
    on: function(star) {
        this._mode(star, true);
    },
    off: function(star) {
        this._mode(star, false);
    },
    isShine: function(star) {
        return (star.className == 'enable');
    },
    match: function(n) {
        return (typeof this._star[n].flg == 'undefined') ? void(0): this._star[n].flg;
    },
    serialize: function() {
        var dig = "";
        var slen = this._star.length;
        for (var i=0; i<slen; i++) {
            dig += (this._star[i].flg) ? '1' : '0';
        }
        return parseInt(dig, 2);
    },
    unserialize: function(arg) {
        var result = new Array();
        var n = new Number(arg);
        var dig = n.toString(2);
        var slen = this._star.length;
        var dlen = slen - dig.length;
        var pat = "";
        for (var i=0; i<dlen; i++) {
            pat += '0';
        }
        dig = pat + dig;
        for (var i=0; i<slen; i++) {
            result.push(dig.charAt(i));
        }
        return result;
    }
};

//tag
Mogel.Tag = function(elem) {
    this.obj = elem;
    this.flg = false;
    this.hightlight = false;
}
Mogel.Tag.prototype = {
    flash: function(bool) {
        if (typeof bool == 'undefined') {
            return this.hightlight;
        } else {
            if (!this.flg) {
                this.hightlight = bool;
                this.obj.style.backgroundColor = bool ? '#FFF68F' : 'transparent';
                this.obj.style.color = '#1874CD'
            }
        }
    }
};

//tag list
Mogel.TagList = function() {
    this._tag = new Object();
    this._relation = new Object();
}
Mogel.TagList.prototype = {
    add: function(tag) {
        this._tag[tag.innerHTML] = new Mogel.Tag(tag);
    },
    _mode: function(label, bool) {
        this._tag[label].flg = bool;
        this._tag[label].obj.style.backgroundColor = bool ? '#00B2EE' : 'transparent';
        this._tag[label].obj.style.color = bool ? '#FFFFFF' : '#1874CD';
    },
    mapping: function(tags) {
        for (var tag in this._tag) {
            if (typeof this._relation[tag] == 'undefined') {
                this._relation[tag] = new Array();
            }
        }
        var len = tags.length;
        for (var i=0; i<len; i++) {
            for (var j=0; j<len; j++) {
                if (tags[i] != tags[j]) {
                    var newtag = true;
                    var rlen = this._relation[tags[i]].length;
                    for (var k=0; k<rlen; k++) {
                        if (this._relation[tags[i]][k] == tags[j]) {
                            newtag = false;
                            break;
                        }
                    }
                    if (newtag) {
                        this._relation[tags[i]].push(tags[j]);
                    }
                }
            }
        }
    },
    match: function(tags) {
        var len = tags.length;
        for (var t in this._tag) {
            if (this._tag[t].flg) {
                if (len == 0 && this._tag[t].obj.innerHTML == "タグ無し") {
                    return true;
                }
                var ok = false;
                for (var i=0; i<len; i++) {
                    if (this._tag[t].obj.innerHTML == tags[i]) {
                        ok = true;
                    }
                }
                if (!ok) {
                    return false;
                }
            }
        }
        return true;
    },
    status: function(label) {
        return this._tag[label].flg;
    },
    on: function(tag) {
        this._mode(tag.innerHTML, true);
    },
    off: function(tag) {
        this._mode(tag.innerHTML, false);
    },
    clear: function() {
        for (var prop in this._tag) {
            this._mode(prop, false);
            this._tag[prop].flash(false);
        }
    },
    serialize: function() {
        var result = new Array();
        for (var prop in this._tag) {
            if (this._tag[prop].flg) {
                result.push(prop);
            }
        }
        return result;
    }
};

//entry
Mogel.Entry = function(elem) {
    this.element = elem;
    this.title = "";
    this.uri = "";
    this.description = "";
    this.date = null;
    this.rate = 0;
    this.tags = new Array();
    this.digest = "";
    this.display = true;
    this.setProp();
}

Mogel.Entry.prototype = {
    setProp: function() {
        var element = null;
        var tmp = new Array();
        var div = this.element.getElementsByTagName('div');
        var dlen = div.length;
        for (var i=0; i<dlen; i++) {
            if (div[i].className == 'entry') {
                element = div[i];
                break;
            }
        }
        this.title =  element.getElementsByTagName('H2')[0].getElementsByTagName('A')[0].innerHTML;
        var p = element.getElementsByTagName('p');
        var plen = p.length;
        for (var i=0; i<plen; i++) {
            if (p[i].className == 'uri') {
                this.uri = p[i].getElementsByTagName('A')[0].innerHTML;
            } else if (p[i].className == 'description') {
                this.description = p[i].innerHTML;
            } else if (p[i].className == 'tags') {
                var tags = p[i].getElementsByTagName('span');
                var tlen = tags.length;
                for (var j=0; j<tlen; j++) {
                    this.tags.push(tags[j].innerHTML);
                }
            } else {
                var span = p[i].getElementsByTagName('span');
                var slen = span.length;
                for (var j=0; j<slen; j++) {
                    if (span[j].className == 'date') {
                        tmp.push(span[j].innerHTML);
                        this.date = new Date(span[j].innerHTML + ' GMT +0900');
                    } else if (span[j].className == 'rate') {
                        var count = 0;
                        var rlen = span[j].innerHTML.length;
                        for (var k=0; k<rlen; k++) {
                            if (span[j].innerHTML.charAt(k) == '★') {
                                count++;
                            } else {
                                break;
                            }
                        }
                        this.rate = count;
                    }
                }
            }
        }
        tmp.push(this.title);
        tmp.push(this.uri);
        tmp.push(this.description);
        tmp.push(this.rate);
        tmp.push(this.tags.join(" "));
        this.digest = tmp.join(" ");
    }
};

//クエリー
Mogel.Query = function(input) {
    this.query = input;
}
Mogel.Query.prototype = {
    scrape: function() {
        var query = this.query.value;
        var len = query.length;
        var rangeMode = "";
        var word = "";
        var words = new Array();
        for (var i=0; i<len; i++) {
            var c = query.charAt(i);
            if (rangeMode == "") {
                if (c == '"' || c == "'") {
                    rangeMode = c;
                    continue;
                } else {
                    if (c == ' ' || c == '　') {
                        if (word.length > 0) {
                            words.push(word);
                            word = "";
                        }
                        continue;
                    } else {
                        word += c;
                    }
                }
            } else {
                if (c == rangeMode) {
                    if (word.length > 0) {
                        words.push(word);
                        word = "";
                    }
                    rangeMode = "";
                    continue;
                } else {
                    word += c;
                }
            }
        }
        if (word.length > 0) {
            words.push(word);
        }
        if (words.length == 0) {
            words.push("");
        }
        return words;
    },
    value: function(input) {
        if (typeof input != 'undefined') {
            this.query.value = input;
        }
        return this.query.value;
    }
};

//entry list
Mogel.EntryList = function(elem) {
    this._entry = new Array();
    this.feedback = elem;
    this.select = "";
}
Mogel.EntryList.prototype = {
    add: function(entry) {
        this._entry.push(entry);
    },
    order: function(obj) {
        this.select = obj.id;
        var cmp = {
            date_desc: function(a, b) { return b.date - a.date; },
            date_asc: function(a, b) { return a.date - b.date; },
            rate_desc: function(a, b) { return (b.rate - a.rate) || (b.date - a.date); },
            rate_asc: function(a, b) { return (a.rate - b.rate) || (a.date - b.date); },
            title_desc: function(a, b) { return (b.title.toUpperCase() < a.title.toUpperCase()) ? 1 : (b.title.toUpperCase() > a.title.toUpperCase()) ? -1 : (b.date - a.date); },
            title_asc: function(a, b) { return (a.title.toUpperCase() < b.title.toUpperCase()) ? 1 : (a.title.toUpperCase() > b.title.toUpperCase()) ? -1 : (a.date - b.date); },
            uri_desc: function(a, b) { return (b.uri.toUpperCase() < a.uri.toUpperCase()) ? 1 : (b.uri.toUpperCase() > a.uri.toUpperCase()) ? -1 : (b.date - a.date); },
            uri_asc: function(a, b) { return (a.uri.toUpperCase() < b.uri.toUpperCase()) ? 1 : (a.uri.toUpperCase() > b.uri.toUpperCase()) ? -1 : (a.date - b.date); }
        };
        this._entry.sort(cmp[obj.id]);
        var len = this._entry.length;
        for (var i=0; i<len; i++) {
            document.getElementById('deck').appendChild(this._entry[i].element);
        }
    },
    counter_bind: function(elem) {
        this.feedback = elem;
    },
    filter: function(query, rate, tags) {
        var result = 0;
        var keywords = query.scrape();
        var len = this._entry.length;
        var klen = keywords.length;
        for (var i=0; i<len; i++) {
            for (var j=0; j<klen; j++) {
                if (this._entry[i].digest.toUpperCase().indexOf(keywords[j].toUpperCase(), 0) >= 0
                    && rate.match(this._entry[i].rate)
                    && tags.match(this._entry[i].tags)) {
                    this._entry[i].display = true;
                } else {
                    this._entry[i].display = false;
                    break;
                }
            }
            if (this._entry[i].display) {
                this._entry[i].element.style.display = 'block';
                result++;
            } else {
                this._entry[i].element.style.display = 'none';
            }
        }
        this.feedback.innerHTML = result;
        return result;
    }
};