/* NTElectrode class */
  
function NTModule(symbol, addr)
{
    this._id = get_unique_id();
    this._valid = false;
    this._symbol = symbol;
    this._addr = addr;
    this._romaddr = null;
    this._type = "";
    this._name = "";
    this._electrodes = new Array();
    this._struct_type = "nt_module_data";

    if(!pcm_define_symbol(symbol, addr, this._struct_type + "*"))
        return;
    
    debug_print("Reads pointer: " + symbol + "->rom", false);

    if(!pcm_read_ptr(symbol + "->rom"))
        return;
        
    // remember our ROM pointer
    this._romaddr = pcm.LastVariable_vValue;

    
    if(!pcm_define_symbol(symbol + "->rom", this._romaddr, "nt_module*"))
        return;

    // try to determine control type dynamically
    if(pcm_read_ptr(symbol + "->rom->interface"))
    {
        var itf = pcm.LastVariable_vValue;

        // by comparing interface pointers with known ones
        for(var mt in MODULE_TYPES)
        {
            if(pcm_get_symbol_info("nt_module_" + MODULE_TYPES[mt] + "_interface"))
            {
                if(itf == pcm.LastSymbolInfo_addr)
                {
                    debug_print("Module at " + this._symbol + " is " + MODULE_TYPES[mt]);    
                    this._type = MODULE_TYPES[mt];
                    break;
                }
            }
        }
    }
   
    // create the module name
    this._name = "module_" + this._type + "_"+ NTModule.All.length;

    // read x->electrodes array
    if(!pcm_read_var(symbol + "->electrodes_cnt", 1))
      return false;
    var el_cnt = pcm.LastVariable_vValue;
    debug_print("Read " + this._symbol + "->electrodes_cnt" + "..." + el_cnt);
    var elarrname = symbol + "->electrodes";
    var eix, elarr = read_ptr_array_cnt(elarrname, el_cnt);
    for(eix=0; eix<elarr.length; eix++)
    {
        // pointer to the nt_electrode object
        var eptr = elarr[eix];

        // electrode already loaded?
        var el = NTElectrode.ByAddr[eptr];

        debug_print("NTModule uses electrode #" + eix + " at 0x" + eptr.toString(16) + ", " + (el ? el.GetName() : "creating..."), false);
        
        // no, create nt_electrode type
        if(!el)
            el = new NTElectrode(this, elarrname + "["+eix+"]", eptr, this._type, true);
        
        if(el.IsValid())
            this._electrodes.push(el);
        else
            debug_print("NTModule uses invalid electrode? 0x" + eptr.toString(16), true);
    }

    // success!
    this._valid = true;

    debug_print("NTModule defined at " + this._symbol + ", name=" + this._name + ", electrodes=" + this._electrodes.length, false);

    if(NTModule.ByAddr[addr])
        alert("NTModule already exists");
    
    NTModule.All.push(this);
    NTModule.ById[this._id] = this;
    NTModule.ByName[this._name] = this;
    NTModule.ByAddr[this._addr] = this;
    NTModule.BySymbol[this._symbol] = this;
}

NTModule.All = new Array();
NTModule.ById = new Array();
NTModule.ByName = new Array();
NTModule.ByAddr = new Array();
NTModule.BySymbol = new Array();
document.NTModule = NTModule;

NTModule.prototype.IsValid = function()
{
    return this._valid;
}

NTModule.prototype.GetName = function()
{
    return this._name;
}

NTModule.prototype.GetSymbol = function()
{
    return this._symbol;
}


NTModule.prototype.GetGui = function()
{
    var str="<p>";
    str += "<i>"+this._type + "</i> detected " + ". Module name: <i>" + this._name +"</i>.</p>";
//    str += Get_control_gui_electrodes();
    var pEl = this._electrodes;
    str += "<center><table id=\""+this._name+"\" style=\"text-align: center; \"><tr><th>Electrode name</th><th>Keydetector</th><th>Raw Cnt</th><th>Baseline Cnt</th><th>signal</th><th>Touch</th><th>flags</th></tr>";
    for(el in pEl)
    {
      str += "<tr><td>"+pEl[el].GetLink()+"</td><td>"+pEl[el].GetKeydetType()+"</td><td>"+pEl[el].GetGuiVar("raw_signal")+"</td><td>"+pEl[el].GetGuiVar("baseline")+"</td><td>"+pEl[el].GetGuiVar("signal")+"</td><td>"+pEl[el].GetGuiTouchSt()+"</td><td>"+pEl[el].GetGuiVar("flags")+"</td></tr>";
    }
    str += "</table></center>";

    return str;
}

