package turgen.dtb;

import turgen.Utils;

/** Segment binarniho souboru*/
public class Segment implements Comparable {
    
    /**Datovy segment*/
    public static final int DATA_SEGMENT=0;
    /**INIT segment*/
    public static final int INIT_SEGMENT=1;
    /**RUN segment*/
    public static final int RUN_SEGMENT=2;
    /**RUNINIT segment*/
    public static final int RUNINIT_SEGMENT=3;
    
    /**Retezcove oznaceni typu segmentu*/
    static final String[] typeStrings={"DATA","INIT","RUN","RUNINIT"};
        
    /**Pocatecni adresa*/
    public int start;
    /**Koncova adresa*/
    public int stop;
    /**Typ segmentu*/
    public int type;
    /**Adresa odskoku pro inicializacni a spousteci segmenty*/
    public int jump;
    
    /**Adresa odskoku 2, jen pro RUN/INIT segmenty*/
    public int jump2;
    
    /**Data segmentu*/
    public int[] data;
    
    /**Nova instance
     *@param s Pocatecni adresa segmentu
     *@param st Koncova adresa segmentu
     *@param t Typ segmentu
     */
    
    public Segment(int s,int st,int t) {
        this(s,st,t,0,0);
    }
    
    /**Nova instance
     *@param s Pocatecni adresa segmentu
     *@param st Koncova adresa segmentu
     *@param t Typ segmentu
     *@param j Skokova adresa
     */
    
    public Segment(int s,int st,int t,int j) {
        this(s,st,t,j,0);
    }
    
    Segment(int s,int st,int t,int j,int j2) {
        start=s;
        stop=st;
        type=t;
        jump=j;
        jump2=j2;
        data=new int[st-s+1];
        if (type==Segment.RUN_SEGMENT || type==Segment.INIT_SEGMENT) {
            data[0]=jump % 256;
            data[1]=jump / 256;
        }
        if (type==Segment.RUNINIT_SEGMENT) {
            data[0]=jump % 256;
            data[1]=jump / 256;
            data[2]=jump2 % 256;
            data[3]=jump2 / 256;
        }
    }
    
    /** retezcova reprezentace segmentu
     *  @return retezcova reprezentace
     */
    public String toString() {
        
        /*Display type*/
        StringBuilder sb = new StringBuilder();
        sb.append(typeStrings[type]);
        sb.append(' ');
        
        /*Display start and end address*/
        String decStart = Utils.padZeros(Integer.toString(start),5);
        String decStop = Utils.padZeros(Integer.toString(stop),5);
        String hexStart = Utils.padZeros(Integer.toHexString(start).toUpperCase(),4);
        String hexStop = Utils.padZeros(Integer.toHexString(stop).toUpperCase(),4);
        
        sb.append(decStart);
        sb.append('-');
        sb.append(decStop);
        sb.append(" [");
        sb.append(hexStart);
        sb.append('-');
        sb.append(hexStop);
        sb.append(']');
        
        if (type==RUN_SEGMENT || type==INIT_SEGMENT) {
            sb.append(' ');
            sb.append('{');
            sb.append(Utils.padZeros(Integer.toString(jump),5));
            sb.append(" [");
            sb.append(Utils.padZeros(Integer.toHexString(jump).toUpperCase(),4));
            sb.append(']');
            sb.append('}');
        }
        if (type==RUNINIT_SEGMENT) {
            sb.append(' ');
            sb.append('{');
            sb.append(Utils.padZeros(Integer.toString(jump),5));
            sb.append(" [");
            sb.append(Utils.padZeros(Integer.toHexString(jump).toUpperCase(),4));
            sb.append(']');
            sb.append(',');
            sb.append(Utils.padZeros(Integer.toString(jump2),5));
            sb.append(" [");
            sb.append(Utils.padZeros(Integer.toHexString(jump2).toUpperCase(),4));
            sb.append(']');
            sb.append('}');
        }
                
        
        
        return sb.toString();
    }
    
   
    
    /** Porovnani dvou segmentu, porovnava se podle pocatecni adresy
     *  @param o Objekt se kterym se ma porovnavat
     */
    public int compareTo(Object o) {
        Segment x =(Segment)o;
        if (x.start<this.start) return +1;
        if (x.start==this.start) return 0; else return -1;
    }
    
    public int[] getFullData() {
        
        int[] retArray = new int[data.length+4];
        retArray[0]=start % 256;
        retArray[1]=start / 256;
        retArray[2]=stop % 256;
        retArray[3]=stop / 256;
        System.arraycopy(data,0,retArray,4,data.length);
        
        return retArray;
    }
}
