package com.moex.asts.export;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import com.moex.asts.export.Description.FieldInfo;
import com.moex.asts.export.Description.TableInfo;
import com.moex.memory.Record;

public class XmlEncoder extends Encoder {

    final static String XML_PROLOG = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<export>";
    final static String XML_ENDING = "</export>";

    XmlEncoder(String filename) {
        super(filename);
    }

    @Override
    protected PrintWriter setup() throws FileNotFoundException, UnsupportedEncodingException {
        PrintWriter result = super.setup();
        result.println(XML_PROLOG);
        return result;
    }

    @Override
    public void close() throws IOException {
        if (writer != null)
            writer.println(XML_ENDING);
        super.close();
    }

    static String toXml(String text) {
        return text
                .replaceAll("\0", "&#0000;")
                .replaceAll("&", "&amp;")
                .replaceAll("<", "&lt;")
                .replaceAll(">", "&gt;")
                .replaceAll("'", "&apos;")
                .replaceAll("\"", "&quot;");
    }

    @Override
    public void encode(TableInfo specs, ClientTable table, Map<String, Object> params) {
        writer.print("\t<");
        writer.print(specs.alias());
        for (Entry<String, Object> param : params.entrySet()) {
            writer.print(' ');
            writer.print(param.getKey());
            writer.print('=');
            writer.print('"');
            writer.print(param.getValue() == null ? "null" :
                toXml(param.getValue().toString()));
            writer.print('"');
        }
        writer.println('>');
        try {
            final String[] names;
            final int[] index;
            if (specs.fields.length == 0) {
                names = table.getColumnNames();
                index = new int[names.length];
                for (int j = 0; j < names.length; j++)
                    index[j] = j;
            } else {
                names = new String[specs.fields.length];
                index = new int[specs.fields.length];
                int j = 0;
                for (FieldInfo field : specs.fields) {
                    names[j] = field.alias();
                    index[j] = table.getColumnIndex(field.source);
                    j++;
                }
            }

            Iterator<Record> i = table.hasPrimaryIndex()
                    ? table.getPrimaryIndex().iterator()
                    : table.iterator();
            while (i.hasNext()) {
                final Record r = i.next();
                writer.print("\t\t<record");
                //writer.println("\t\t<record>");
                for (int j = 0; j < names.length; j++) {
                    if (index[j] < 0 || r.isNull(index[j]))
                        continue;

                    writer.print(" ");
                    writer.print(names[j]);
                    writer.print("=\"");
                    writer.print(toXml(r.asString(index[j])));
                    writer.print("\"");
//                    writer.print("\t\t\t<");
//                    writer.print(names[j]);
//                    if (r.isNull(index[j]))
//                        writer.println("/>");
//                    else {
//                        writer.print('>');
//                        writer.print(toXml(r.asString(index[j])));
//                        writer.print("</");
//                        writer.print(names[j]);
//                        writer.println(">");
//                    }
                }
                writer.println(" />");
                //writer.println("\t\t</record>");
            }
        } finally {
            writer.print("\t</");
            writer.print(specs.alias());
            writer.println('>');
            writer.flush();
        }
    }

}
