package org.aion.zero.impl.config;

import com.google.common.base.Objects;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import org.aion.log.AionLoggerFactory;
import org.slf4j.Logger;

public class CfgApiZmq {

    public static final String ZMQ_KEY_DIR = "zmq_keystore";

    CfgApiZmq() {
        this.active = true;
        this.ip = "127.0.0.1";
        this.port = 8547;
        this.filtersEnabled = true;
        this.blockSummaryCacheEnabled = false;
        this.secureConnectEnabled = false;
    }

    protected boolean active;
    protected String ip;
    protected int port;
    private boolean filtersEnabled;
    private boolean blockSummaryCacheEnabled;
    private boolean secureConnectEnabled;

    private static Logger LOG_GEN = AionLoggerFactory.getLogger("GEN");

    public void fromXML(final XMLStreamReader sr) throws XMLStreamException {
        this.active = Boolean.parseBoolean(sr.getAttributeValue(null, "active"));
        this.ip = sr.getAttributeValue(null, "ip");
        this.port = Integer.parseInt(sr.getAttributeValue(null, "port"));

        // get the nested elements
        loop:
        while (sr.hasNext()) {
            int eventType = sr.next();
            switch (eventType) {
                case XMLStreamReader.START_ELEMENT:
                    String elementName = sr.getLocalName().toLowerCase();
                    switch (elementName) {
                        case "filters-enabled":
                            try {
                                filtersEnabled = Boolean.parseBoolean(ConfigUtil.readValue(sr));
                            } catch (Exception e) {
                                LOG_GEN.warn(
                                        "failed to read config node: aion.api.zmq.filters-enabled; using preset: {}\n {}"
                                                + this.filtersEnabled,
                                        e);
                                e.printStackTrace();
                            }
                            break;
                        case "block-summary-cache":
                            try {
                                blockSummaryCacheEnabled = Boolean.parseBoolean(ConfigUtil.readValue(sr));
                            } catch (Exception e) {
                                LOG_GEN.warn(
                                        "failed to read config node: aion.api.zmq.block-summary-cache; using preset: {}\n {}",
                                        this.blockSummaryCacheEnabled,
                                        e);
                            }
                            break;
                        case "secure-connect":
                            try {
                                secureConnectEnabled = Boolean.parseBoolean(ConfigUtil.readValue(sr));
                            } catch (Exception e) {
                                LOG_GEN.warn(
                                        "failed to read config node: aion.api.zmq.secure-connect; using preset: {}\n {}"
                                                + this.secureConnectEnabled,
                                        e);
                            }
                            break;
                        default:
                            ConfigUtil.skipElement(sr);
                            break;
                    }
                    break;
                case XMLStreamReader.END_ELEMENT:
                    break loop;
            }
        }

        sr.next();
    }

    String toXML() {
        final XMLOutputFactory output = XMLOutputFactory.newInstance();
        output.setProperty("escapeCharacters", false);
        XMLStreamWriter xmlWriter;
        String xml;
        try {
            // <rpc active="false" ip="127.0.0.1" port="8545"/>

            Writer strWriter = new StringWriter();
            xmlWriter = output.createXMLStreamWriter(strWriter);
            xmlWriter.writeCharacters("\r\n\t\t");
            xmlWriter.writeStartElement("java");

            xmlWriter.writeAttribute("active", this.active ? "true" : "false");
            xmlWriter.writeAttribute("ip", this.ip);
            xmlWriter.writeAttribute("port", this.port + "");

            xmlWriter.writeCharacters("\r\n\t\t\t");
            xmlWriter.writeStartElement("secure-connect");
            xmlWriter.writeCharacters(String.valueOf(this.secureConnectEnabled));
            xmlWriter.writeEndElement();

            xmlWriter.writeCharacters("\r\n\t\t");
            xmlWriter.writeEndElement();
            xml = strWriter.toString();
            strWriter.flush();
            strWriter.close();
            xmlWriter.flush();
            xmlWriter.close();
            return xml;
        } catch (IOException | XMLStreamException e) {
            e.printStackTrace();
            return "";
        }
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public boolean getActive() {
        return this.active;
    }

    public String getIp() {
        return this.ip;
    }

    public int getPort() {
        return this.port;
    }

    public boolean isFiltersEnabled() {
        return this.filtersEnabled;
    }

    public boolean isBlockSummaryCacheEnabled() {
        return this.blockSummaryCacheEnabled;
    }

    public boolean isSecureConnectEnabledEnabled() {
        return this.secureConnectEnabled;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CfgApiZmq cfgApiZmq = (CfgApiZmq) o;
        return active == cfgApiZmq.active
                && port == cfgApiZmq.port
                && filtersEnabled == cfgApiZmq.filtersEnabled
                && blockSummaryCacheEnabled == cfgApiZmq.blockSummaryCacheEnabled
                && secureConnectEnabled == cfgApiZmq.secureConnectEnabled
                && Objects.equal(ip, cfgApiZmq.ip);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(
                active, ip, port, filtersEnabled, blockSummaryCacheEnabled, secureConnectEnabled);
    }
}

// get the nested elements
package org.aion.zero.impl.config;

import com.google.common.base.Objects;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import org.aion.log.AionLoggerFactory;
import org.slf4j.Logger;

public class CfgApiZmq {

    public static final String ZMQ_KEY_DIR = "zmq_keystore";

    CfgApiZmq() {
        this.active = true;
        this.ip = "127.0.0.1";
        this.port = 8547;
        this.filtersEnabled = true;
        this.blockSummaryCacheEnabled = false;
        this.secureConnectEnabled = false;
    }

    protected boolean active;
    protected String ip;
    protected int port;
    private boolean filtersEnabled;
    private boolean blockSummaryCacheEnabled;
    private boolean secureConnectEnabled;

    private static Logger LOG_GEN = AionLoggerFactory.getLogger("GEN");

    public void fromXML(final XMLStreamReader sr) throws XMLStreamException {
        this.active = Boolean.parseBoolean(sr.getAttributeValue(null, "active"));
        this.ip = sr.getAttributeValue(null, "ip");
        this.port = Integer.parseInt(sr.getAttributeValue(null, "port"));

        // get the<SUF>
        loop:
        while (sr.hasNext()) {
            int eventType = sr.next();
            switch (eventType) {
                case XMLStreamReader.START_ELEMENT:
                    String elementName = sr.getLocalName().toLowerCase();
                    switch (elementName) {
                        case "filters-enabled":
                            try {
                                filtersEnabled = Boolean.parseBoolean(ConfigUtil.readValue(sr));
                            } catch (Exception e) {
                                LOG_GEN.warn(
                                        "failed to read config node: aion.api.zmq.filters-enabled; using preset: {}\n {}"
                                                + this.filtersEnabled,
                                        e);
                                e.printStackTrace();
                            }
                            break;
                        case "block-summary-cache":
                            try {
                                blockSummaryCacheEnabled = Boolean.parseBoolean(ConfigUtil.readValue(sr));
                            } catch (Exception e) {
                                LOG_GEN.warn(
                                        "failed to read config node: aion.api.zmq.block-summary-cache; using preset: {}\n {}",
                                        this.blockSummaryCacheEnabled,
                                        e);
                            }
                            break;
                        case "secure-connect":
                            try {
                                secureConnectEnabled = Boolean.parseBoolean(ConfigUtil.readValue(sr));
                            } catch (Exception e) {
                                LOG_GEN.warn(
                                        "failed to read config node: aion.api.zmq.secure-connect; using preset: {}\n {}"
                                                + this.secureConnectEnabled,
                                        e);
                            }
                            break;
                        default:
                            ConfigUtil.skipElement(sr);
                            break;
                    }
                    break;
                case XMLStreamReader.END_ELEMENT:
                    break loop;
            }
        }

        sr.next();
    }

    String toXML() {
        final XMLOutputFactory output = XMLOutputFactory.newInstance();
        output.setProperty("escapeCharacters", false);
        XMLStreamWriter xmlWriter;
        String xml;
        try {
            // <rpc active="false" ip="127.0.0.1" port="8545"/>

            Writer strWriter = new StringWriter();
            xmlWriter = output.createXMLStreamWriter(strWriter);
            xmlWriter.writeCharacters("\r\n\t\t");
            xmlWriter.writeStartElement("java");

            xmlWriter.writeAttribute("active", this.active ? "true" : "false");
            xmlWriter.writeAttribute("ip", this.ip);
            xmlWriter.writeAttribute("port", this.port + "");

            xmlWriter.writeCharacters("\r\n\t\t\t");
            xmlWriter.writeStartElement("secure-connect");
            xmlWriter.writeCharacters(String.valueOf(this.secureConnectEnabled));
            xmlWriter.writeEndElement();

            xmlWriter.writeCharacters("\r\n\t\t");
            xmlWriter.writeEndElement();
            xml = strWriter.toString();
            strWriter.flush();
            strWriter.close();
            xmlWriter.flush();
            xmlWriter.close();
            return xml;
        } catch (IOException | XMLStreamException e) {
            e.printStackTrace();
            return "";
        }
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public boolean getActive() {
        return this.active;
    }

    public String getIp() {
        return this.ip;
    }

    public int getPort() {
        return this.port;
    }

    public boolean isFiltersEnabled() {
        return this.filtersEnabled;
    }

    public boolean isBlockSummaryCacheEnabled() {
        return this.blockSummaryCacheEnabled;
    }

    public boolean isSecureConnectEnabledEnabled() {
        return this.secureConnectEnabled;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CfgApiZmq cfgApiZmq = (CfgApiZmq) o;
        return active == cfgApiZmq.active
                && port == cfgApiZmq.port
                && filtersEnabled == cfgApiZmq.filtersEnabled
                && blockSummaryCacheEnabled == cfgApiZmq.blockSummaryCacheEnabled
                && secureConnectEnabled == cfgApiZmq.secureConnectEnabled
                && Objects.equal(ip, cfgApiZmq.ip);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(
                active, ip, port, filtersEnabled, blockSummaryCacheEnabled, secureConnectEnabled);
    }
}
