/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package svgconverter;

import java.util.*;
import java.io.*;
import java.util.*;
import java.io.File;

/**
 *
 * @author Pap
 */
public class BitWriter {
    LinkedList<Boolean> bits = new LinkedList<Boolean>();

    class Tag {
        String purpose;
        int cnt;
    }
    HashMap<String, Tag> map = new HashMap<String, Tag>();
/*
    public void WriteUnsignedInt16(int val) {
        for(int i = 15; i >= 0; i--) {
            boolean v = ((val & (1 << i)) != 0);
            this.bits.add(v);
        }
    }

    public void WriteSignedByte8(int val) {
        if(val < 0)
            this.bits.add(true);
        else
            this.bits.add(false);
        int v = Math.abs(val);
        if(v > 127) {
            System.out.println("Error: Writing byte > 127");
            System.exit(0);
        }
        for(int i = 6; i >= 0; i--) {
            boolean b = ((v & (1 << i)) != 0);
            this.bits.add(b);
        }
    }

    public void WriteUnsignedByte8(int val) {
        if(val > 255) {
            System.out.println("Error: Writing byte > 255");
            System.exit(0);
        }
        for(int i = 7; i >= 0; i--) {
            boolean b = ((val & (1 << i)) != 0);
            this.bits.add(b);
        }
    }
*/

    public void AddPurpose(String purpose, int bits) {
        Tag t = this.map.get(purpose);
        if(t == null) {
            t = new Tag();
            t.purpose = purpose;
            t.cnt = 0;
            this.map.put(purpose, t);
        } else {
            if(!purpose.equals(t.purpose)) {
                System.out.println("Error");
                System.exit(0);
            }
        }
        t.cnt+= bits;
    }

    public void PrintStats() {
        Iterator<Tag> iter = this.map.values().iterator();
        while(iter.hasNext()) {
            Tag t = iter.next();
            System.out.println(t.purpose + ": " + t.cnt + " bits (" + (t.cnt / 8) + " bytes)");
        }
    }

    public void WriteUnsignedInt(String purpose, int val, int bits) {
        this.AddPurpose(purpose, bits);
        int max = (int)Math.pow(2, bits);
        if(val >= max) {
            System.out.println("Error writing " + purpose + ": Writing int > " + max);
            System.exit(0);
        }
        for(int i = bits - 1; i >= 0; i--) {
            boolean b = ((val & (1 << i)) != 0);
            this.bits.add(b);
        }
    }

    public void WriteSignedInt(String purpose, int val, int bits) {
        this.AddPurpose(purpose, bits);
        if(val < 0)
            this.bits.add(true);
        else
            this.bits.add(false);
        int v = Math.abs(val);
        int max = (int)Math.pow(2, bits - 1);
        if(v >= max) {
            System.out.println("Error writing " + purpose + ": Writing int > " + max);
            System.exit(0);
        }
        for(int i = bits - 2; i >= 0; i--) {
            boolean b = ((v & (1 << i)) != 0);
            this.bits.add(b);
        }
    }

    public void WriteFile(String fileName) {
        try {
            FileOutputStream fstream = new FileOutputStream("data/output.esvg");
            // Wrap the FileOutputStream with a DataOutputStream
            DataOutputStream data_out = new DataOutputStream (fstream);
            int cur = 0;
            int l = 0;
            Iterator<Boolean> iter = this.bits.iterator();
            while(iter.hasNext()) {
                if(l == 8) {
                    if(cur > 127)
                        cur = cur - 256;
                    data_out.writeByte(cur);
//                    System.out.println("Writing " + cur);
                    l = 0;
                    cur = 0;
                }
                cur = cur * 2;
                if(iter.next())
                    cur += 1;
                l++;
            }
            if(l > 0) {
                while(l < 8) {
                    cur = cur * 2;
                    l++;
                }
                if(cur > 127)
                    cur = cur - 256;
                data_out.writeByte(cur);
            }
            fstream.close ();
        } catch (Exception e) {
            e.printStackTrace();;
            System.out.println("Error writing out file");
            System.exit(0);
        }
    }

}
