/**
 * Serialize and deserialize Objects into binary files.
 * This version uses base64 encoding for strings.
 */
package basics.filesystem.serializer;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;

/**
 * @author Robert Casties
 *
 */
public class SerializerFileFlatEncoded extends SerializerFileFlat implements Serializer {

	private String CHARSET_ENCODING = "UTF-8";

	private String decode(String value) {
        if (value == null) {
            return null;
        }
	    String line = null;
        byte[] encbuf;
        try {
            // read as ASCII because its base64
            encbuf = value.getBytes("US-ASCII");
            byte[] buffer = Base64.decodeBase64(encbuf);
            line = new String(buffer, CHARSET_ENCODING);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return line;
	}
	
    private String encode(String value) {
        if (value == null) {
            return "";
        }
        String line = null;
        byte[] buffer;
        try {
            buffer = value.getBytes(CHARSET_ENCODING);
            byte[] encbuf = Base64.encodeBase64(buffer);
            // write as ASCII because its base64
            line = new String(encbuf, "US-ASCII");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return line;
    }

	/* (non-Javadoc)
	 * @see basics.filesystem.serializer.SerializerFileFlat#readString()
	 */
	public String readString() throws IOException {
		String line = in.nextLine();
		return decode(line);
	}

	/* (non-Javadoc)
	 * @see basics.filesystem.serializer.SerializerFileFlat#write(java.lang.String)
	 */
	public void write(String value) throws IOException {
		String line = encode(value);
		out.write(line);
	}

	/* (non-Javadoc)
	 * @see basics.filesystem.serializer.SerializerBase#readStringRaw()
	 */
	public String readStringRaw() throws IOException {
		// use unencoded read from FileFlat
		return super.readString();
	}

	/* (non-Javadoc)
	 * @see basics.filesystem.serializer.SerializerBase#writeRaw(java.lang.String)
	 */
	public void writeRaw(String value) throws IOException {
		// use unencoded write from FileFlat
		super.write(value);
	}

    /* writeMap implementation that puts keys and values in one line.
     * @see basics.filesystem.serializer.SerializerBase#write(java.util.Map)
     */
    public void write(Map<String, String> map) throws IOException {
        int size = map.size();
        write(size);
        for (String key: map.keySet()) {
            String val = map.get(key);
            out.write(encode(key)+" :: "+encode(val));
        }
    }
    
    /* (non-Javadoc)
     * @see basics.filesystem.serializer.SerializerBase#readStringMap()
     */
    public Map<String, String> readStringMap() throws IOException {
        int size = readInt();
        Map<String,String> map = new HashMap<String,String>();
        for(int i = 0; i < size; i++) {
            String line = in.nextLine();
            String[] keyval = line.split("\\S*::\\s*");
            map.put(decode(keyval[0]),(keyval.length>1)?decode(keyval[1]):"");
        }
        return map;
    }


}
