package org.commcare.android.logging;

import org.commcare.android.database.SqlStorage;
import org.commcare.android.javarosa.DeviceReportElement;
import org.commcare.android.javarosa.DeviceReportWriter;
import org.javarosa.core.log.LogEntry;
import org.javarosa.core.log.StreamLogSerializer;
import org.javarosa.core.model.utils.DateUtils;
import org.javarosa.core.services.storage.EntityFilter;
import org.javarosa.core.util.SortedIntSet;
import org.xmlpull.v1.XmlSerializer;

import java.io.IOException;
import java.util.Hashtable;

/**
 * Convert xpath error logs to xml
 *
 * @author Phillip Mates (pmates@dimagi.com).
 */
public class XPathErrorSerializer
        extends StreamLogSerializer
        implements DeviceReportElement {
    private final SqlStorage<XPathErrorEntry> errorLogStorage;
    private XmlSerializer serializer;

    public XPathErrorSerializer(final SqlStorage<XPathErrorEntry> logStorage) {
        errorLogStorage = logStorage;
        this.setPurger(new Purger() {
            @Override
            public void purge(final SortedIntSet IDs) {
                logStorage.removeAll(new EntityFilter<LogEntry>() {
                    public int preFilter(int id, Hashtable<String, Object> metaData) {
                        return IDs.contains(id) ? PREFILTER_INCLUDE : PREFILTER_EXCLUDE;
                    }

                    public boolean matches(LogEntry e) {
                        throw new RuntimeException("can't happen");
                    }
                });
            }
        });
    }

    @Override
    public void writeToDeviceReport(XmlSerializer serializer) throws IOException {
        this.serializer = serializer;

        serializer.startTag(DeviceReportWriter.XMLNS, "xpath_error_subreport");

        try {
            for (XPathErrorEntry entry : errorLogStorage) {
                serializeLog(entry.getID(), entry);
            }
        } finally {
            serializer.endTag(DeviceReportWriter.XMLNS, "xpath_error_subreport");
        }
    }

    @Override
    protected void serializeLog(LogEntry entry) throws IOException {
        final XPathErrorEntry errorEntry = (XPathErrorEntry)entry;
        String dateString =
                DateUtils.formatDateTime(errorEntry.getTime(), DateUtils.FORMAT_ISO8601);

        serializer.startTag(DeviceReportWriter.XMLNS, "xpath_error");
        try {
            serializer.attribute(null, "date", dateString);
            writeText("type", errorEntry.getType());
            writeText("msg", errorEntry.getMessage());
            writeText("ssn", errorEntry.getSessionPath());
            writeText("vsn", errorEntry.getAppVersion() + "");
            writeText("app_id", errorEntry.getAppId());
            writeText("expr", errorEntry.getExpression());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            serializer.endTag(DeviceReportWriter.XMLNS, "xpath_error");
        }
    }

    private void writeText(String element, String text)
            throws IllegalArgumentException, IllegalStateException, IOException {
        serializer.startTag(DeviceReportWriter.XMLNS, element);
        try {
            serializer.text(text);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            serializer.endTag(DeviceReportWriter.XMLNS, element);
        }
    }
}

@@ -829,24 +829,176 @@
 erializer;%0A%0A
+    /**%0A     * Report format version for ability to dispatch different parser on server%0A     */%0A    private static final int ERROR_FORMAT_VERSION = 1;%0A%0A
     public X
@@ -1057,32 +1057,32 @@
 %3E logStorage) %7B%0A
-
         errorLog
@@ -1869,37 +1869,36 @@
 tWriter.XMLNS, %22
-xpath
+user
 _error_subreport
@@ -1900,16 +1900,90 @@
 eport%22);
+%0A        serializer.attribute(null, %22version%22, ERROR_FORMAT_VERSION + %22%22);
 %0A%0A      
@@ -2189,29 +2189,28 @@
 ter.XMLNS, %22
-xpath
+user
 _error_subre
@@ -2550,37 +2550,36 @@
 tWriter.XMLNS, %22
-xpath
+user
 _error%22);%0A      
@@ -2778,17 +2778,21 @@
 eText(%22s
-s
+essio
 n%22, erro
@@ -2841,17 +2841,21 @@
 eText(%22v
-s
+ersio
 n%22, erro
@@ -3141,21 +3141,20 @@
 XMLNS, %22
-xpath
+user
 _error%22)

Add report version and change xpath_ to user_