/*
 * Neuron.java
 *
 * Created on 4 of August 2004, 21:54
 */

/**
 *
 * @author  Eng. Paulo Roque Silva
 */
import java.util.*;
import java.io.*;

public class Neuron implements Serializable {
    public static final long    serialVersionUID = 00012012L; // Data version
    static final int			Ndendrites = 5;// #ArrayList dendrites memory allocated by default
    int			 				id,            // Self IDentification
    							value,		   // #times that neuron had fired
    							senses,		   // # of senses fired
    							totalSenses,   // total of fired-or-not sense information
								threshold,     // Level to react (in percentage 0-100) (to Past nodes)
								thresholdINIT; // Level to react (in percentage 0-100) (to Past nodes) Initial
	//							balance;       // count steps as BALANCE
    ArrayList<Signal>		  	dendrites;     // Signals that neuron is listening or act
    boolean						fire,          // Neuron is apt to fire
    							standby,       // Neuron is in standby for surviving learn (to Act nodes)
    							keep,	       // Neuron keeps input
    							end;           // if true, neuron thread is to finish
    int 		              	pointer,       // actual memory step
    							step;          // # of interactions

    /** Creates a new instance of Neuron */
    public Neuron(int neuronId, int th) {

        threshold = th;
        thresholdINIT = th;
        id = neuronId;
        value = 0;              // never has fired
        totalSenses = 0;
        senses= 0;
  //      balance = 0;
        dendrites = new ArrayList<Signal>(Ndendrites);
        fire = false;
        standby = false;        // waits for random fires
        keep = false;
        step = 0;               // step that past neuron starts to record
        pointer = 0;
        end = false;			// the simulation doesn't end yet
    }

    public void setThreshold(int th) {    // neuron has fired again
        
    	threshold = th;
    }
    
    public void addValue() {    // neuron has fired again
        
    	value += 1;
    }
    
    public void setValue(int v) {
        
    	value = v;
    }
    
    public void addTotalSenses() {
        
    	totalSenses += 1;
    }
    
    public void setTotalSenses(int tv) {
        
    	totalSenses = tv;
    }
    
    public void addSense() {
        
    	senses += 1;
    }
    
    public void setSenses(int s) {
        
    	senses = s;
    }
    
//    public void addBalance() {
        
//    	balance += 1;
//    }
    
//    public void setBalance(int b) {
        
//    	balance = b;
//    }
    
    public Signal getDendrite(int n) {      // n starts at 0 - n is not the emitter but an index

    	return (Signal)dendrites.get(n);
    }

    public void addDendriteCredit(int e, float pw) {

        dendrites.add(new Signal(e, pw));
    }
    
    public boolean newDendrite(int e) {

        boolean isNew;
        int		i;
        
        isNew =true;
        for (i=0; i<dendrites.size(); i++)
            if (getDendrite(i).emitter == e)
                isNew = false;
        return isNew;
    }
    
    // add a signal or dendrite with a emitted id <e> and a power <pw>
    public void addDendrite(int e, float pw) {

        boolean isNew;
        
        isNew = newDendrite(e);
        if (isNew)
            dendrites.add(new Signal(e, pw));
    }
    
    public void clearSignals() {
    	int i;

    	for (i=0; i<dendrites.size(); i++)
    		getDendrite(i).setActive(false);
    }

    public void clearDendrite() { 		// ArrayList to clear all: dendrites.clear();
        
        dendrites.clear();
    }
    
//    public void removeDendrite(int n) { // For Act Neurons only - ArrayList to clear all: dendrites.clear();
//        
//    	dendrites.remove(n);
//    }
    
    public boolean powerOfFire() {  // For Past Neurons only
        float	activeCredit,				// Sum of all 1/(log(abs(recP-actP+1))+1) from active signal
        		nActives;					// # of active dendrites or signals
    	int		i;							// index
    	float   x;							// Absolute difference between Powers Ids
        
        nActives = 0;
    	activeCredit = 0;
        for (i=0; i<dendrites.size(); i++)
            if (getDendrite(i).active) {    // Set activePercentCredit
               	nActives += 1;
                x = Math.abs(getDendrite(i).recPower - getDendrite(i).actPower);
                if (x > Liberu.MaxInSense)
                	x = Liberu.MaxInSense;
        		                            // VER TI-86 graph 14
                activeCredit += (Liberu.MaxInSense - x) * 100 / Liberu.MaxInSense;
            }
    	fire = false;
    	if (nActives == 0) nActives = 1;
        if (activeCredit / nActives >= threshold) {   // percentage average of active
        	fire = true;
//        	value += 1;
        	if (thresholdINIT == threshold)
        		threshold = threshold - (int)(threshold * Net.Habit / 100);
        }
        return fire;
    }

  	public void setFire(boolean fi) {
        
        fire = fi;
    }
    
  	public void setStandby(boolean st) {
        
        standby = st;
    }

  	public void setKeep(boolean kp) {
        
        keep = kp;
    }

  	public void setEnd(boolean ed) {
        
        end = ed;
    }

    public void addStep() {
        
        step += 1;
    }

    public void addPointer() {
        
        pointer += 1;
    }

    public void setPointer(int i) {
        
        pointer = i;
    }
}
