//-------------------------------------------- Event --------------------------------------------
function Event(_jHTMLElement, _owner) {
    Item.apply(this, arguments);
    if (!arguments.length) return this;
}
Event.prototype = new Item();
Event.fromEntityID = function fromEntityID(entityid) {
    return HTMLObject.fromID("EVT", entityid);
}

Event.prototype.moved = function moved(latlng, marker) {
    if (window.event_moved) window.event_moved(this, latlng, marker);
}

//-------------------------------------------- Business --------------------------------------------
function Business(_jHTMLElement, _owner) {
    Item.apply(this, arguments);
    if (!arguments.length) return this;

    //will be 1-many in future
    this.branchid = this.hV(".branchid");

    //kids
    this.pnss        = [];                          //need to maintain the order of priority: 1st PNS is the primary one
    var pns, pnss    = this.hV(".pnss.xtransport"); //comma delimited PNS@id xtransport list
    var pnsid, apnss = pnss.split(',');
    for (var i = 0; i < apnss.length; i++) {
        pnsid = apnss[i];
        if (pnsid) {
            if (pns = HTMLObject.fromID("PNS", pnsid)) {
                this.pnss.push(pns);
                pns.addBusiness(this);
            } else cerror("pns [" + pnsid + "] not found");
        }
    }

    cinfo("pnss [" + this.pnss + "]");
}
Business.prototype = new Item();
Business.fromEntityID = function fromEntityID(entityid) {
    return HTMLObject.fromID("BUS", entityid);
}

Business.prototype.firstPNSrelevantToTLC = function firstPNSrelevantToTLC(tlc) {
    //PNS are in priority order
    //1st is the standard representation of the business
    //the remainder are the order of priority that they should be shown in any given TLC
    //this function gets the first priority PNS in a given TLC
    //returns null on no relevant PNS: check your return value!
    var pns;
    for (var i = 0; i < this.pnss.length; i++) {
        pns = this.pnss[i];
        if (pns.tlc == tlc) return pns;
    }
}
Business.prototype.moved = function moved(latlng, marker) {
    if (window.business_moved) window.business_moved(this, latlng, marker);
}

//------------------------------------------- TLC -------------------------------------------
function TLC(_jHTMLElement, _map) {
    HTMLObject.apply(this, arguments);
    if (!arguments.length) return this;
    var self = this;
    
    //base values
    this.map    = _map;
    this.name   = this.jHTMLElement.children(".name").text();
    this.colour = this.hV(".colour");
    this.marker = this.hI(".marker").attr("src");
    cgroup("TLC registration [" + this + "]");
    cinfo("colour:" + this.colour);
    cinfo("marker:" + this.marker);
    
    //kids
    this.businesses = new Object(); //need fast lookup: businesses register themselves through PNS
    this.pnss       = [];           //array is fine (not used)
    this.jHTMLElement.find(".producttypes > li").each(function(i, _HTMLElement){
        self.pnss.push(new PNS($(_HTMLElement), self));
    });
    cinfo("PNS [" + this.pnss + "]");
    cgroupend();
    
    //events
    this.jHTMLElement.bind("expanded",  
        (this.id ? 
            function(e){return self.select(e);} :
            function(e){return self.reset(e);}
        )
    );
    this.jHTMLElement.bind("compacted", function(e){return self.reset(e);});
}
TLC.prototype          = new HTMLObject();
TLC.prototype.current  = null;
TLC.prototype.toString = function toString(){return "[" + this.name + ":" + this.hid + "]";}

TLC.prototype.select = function select(e) {
    var self = this;
    setTimeout(function(){self.select_defered(e);}, 0);
}
TLC.prototype.select_defered = function select_defered(e) {
    TLC.prototype.current = this;
    PNS.prototype.current = null;
    //business changes (if expanded)
    //assemble array of businesses in this group
    var business, relevance;
    cgroup("selecting TLC [" + this.name + ":" + this.id + "]");
    //change businesses: cycle through all businesses (allows checking of non-relevant)
    //because they all need to change from unknown previous state
    for (var i in Item.prototype.items) {
        business  = Item.prototype.items[i];
        if (business.item_class_type == 'Business') {
            relevance = (this.businesses[business.id] != null);
            business.relevant(relevance);
            if (relevance) {
                //relevant: we need to morph the marker into the PNS that is relevant to this TLC
                //always 20x34
                business.revert_original();
                var relevantPNS = business.firstPNSrelevantToTLC(this);
                if (relevantPNS) business.change_icon(relevantPNS.marker);
                else             business.change_icon(this.marker);
                business.change_size(20, 34);
            } else {
                //not relevant so show original but small
                if (business.pnss.length) business.change_icon('/societycard/images/marker_packs/' + business.pnss[0].tlc.colour + '/dot.png');
                else                      business.change_icon('/societycard/images/dot.png');
                business.change_shadow();
                business.change_size(12, 12);
                /*
                business.revert_original();
                business.change_size(12, 20);
                */
            }
            cinfo("business [" + business + "] relevance [" + relevance + "]");
        }
    }
    cgroupend();
    filter_change();
    e.stopPropagation();
    e.preventDefault();
    return false;
}

TLC.prototype.reset = function reset(e) {
    //reset all businesses
    var business;
    if (Item.prototype.highlighted) Item.prototype.highlighted.dehighlight();
    TLC.prototype.current = null;
    PNS.prototype.current = null;
    cinfo("resetting");
    for (var i in Item.prototype.items) {
        business = Item.prototype.items[i];
        if (business.item_class_type == 'Business') {
            business.relevant(true);
            business.revert_original(); //changes size and image back to the original image (if different from current)
        }
    }
    filter_change();
    e.stopPropagation();
    e.preventDefault();
    return false;
}

//------------------------------------------- PNS -------------------------------------------
function PNS(_jHTMLElement, _tlc) {
    HTMLObject.apply(this, arguments);
    if (!arguments.length) return this;
    var self = this;
    
    //base values
    this.tlc      = _tlc;
    this.name     = this.hV(".name");
    this.icon     = this.hI(".icon").attr("src");
    this.marker   = this.hI(".marker").attr("src");
    cgroup("PNS [" + this + "]");
    cinfo("icon:"   + this.icon);
    cinfo("marker:" + this.marker);
    cgroupend();
    
    //kids
    this.businesses = new Object(); //fast lookup. businesses register themselves (next)
    
    //events
    this.jHTMLElement.click(function(e){return self.select(e);});
}
PNS.prototype          = new HTMLObject();
PNS.prototype.current  = null;
PNS.prototype.toString = function toString(){return "[" + this.name + ":" + this.hid + "]";}
PNS.prototype.addBusiness = function addBusiness(business) {
    //update fast lookups
    this.businesses[business.id] = business;
    this.tlc.businesses[business.id] = business;
}

PNS.prototype.select = function select(e) {
    TLC.prototype.current = this.tlc; //not necessary but just in case UI has got in a mess
    PNS.prototype.current = this;
    //change businesses: cycle through all businesses (allows checking of non-relevant)
    //because they all need to change from unknown previous state
    cgroup("selecting PNS [" + this.name + ":" + this.businesses + "]");
    var business, relevance, letterid = 1;
    for (var i in Item.prototype.items) {
        business = Item.prototype.items[i];
        if (business.item_class_type == 'Business') {
            relevance = (this.businesses[business.id] != null);
            business.relevant(relevance);
            if (relevance) {
                //lettered markers are all 20x34
                business.change_icon('/societycard/images/marker_packs/' + this.tlc.colour + '/' + letterid++ + '.png');
                business.change_size(20, 34);
            } else {
                //original (primary) marker but small
                if (business.pnss.length) business.change_icon('/societycard/images/marker_packs/' + business.pnss[0].tlc.colour + '/dot.png');
                else                      business.change_icon('/societycard/images/dot.png');
                business.change_shadow();
                business.change_size(12, 12);
                /*
                business.revert_original();
                business.change_size(12, 20);
                */
            }
            cinfo("[" + business.title + "] relevance [" + relevance + "]");
        }
    }
    cgroupend();
    filter_change();
    e.stopPropagation();
    e.preventDefault();
    return false;
}
