// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.bridge.util;

import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;

public class XSerializerXmlAdapter implements XSerializerAdapter {

    private XSerializer serializer;

    public XSerializerXmlAdapter() {
    }

    @Override
    public void setSerializer(XSerializer serializer) {
        this.serializer = serializer;
    }

    @Override
    public void beginElement(String element, String namespace, int indentLevel, PrintWriter writer) {
        indent(true, indentLevel, writer);
        writer.print("<" + element);
        if (namespace != null && !namespace.isEmpty()) {
            writer.print(" xmlns=\"");
            writer.print(namespace);
            writer.print("\"");
        }
        writer.print(">");
    }

    @Override
    public void endElement(String element, int indentLevel, PrintWriter writer) {
        indent(true, indentLevel, writer);
        writer.print("</" + element + ">");
    }

    @Override
    public void writeElement(String elementName, String itemName, Object value, Field f, int indentLevel, PrintWriter writer) {
        Class<?> fieldType = f.getType();
        if (!serializer.isComposite(fieldType)) {
            if (fieldType == Date.class) {
                if (value != null) {
                    indent(true, indentLevel, writer);
                    writer.print("<" + elementName + ">");
                    writer.print(DateHelper.getGMTDateFormat("yyyy-MM-dd").format((Date)value) + "T" + DateHelper.getGMTDateFormat("HH:mm:ss").format((Date)value) +
                        ".000Z");
                    writer.print("</" + elementName + ">");
                } else {
                    if (!serializer.omitNullField(f)) {
                        indent(true, indentLevel, writer);
                        writer.print("<" + elementName + "/>");
                    }
                }
            } else if (fieldType == Calendar.class) {
                if (value != null) {
                    indent(true, indentLevel, writer);

                    Date dt = ((Calendar)value).getTime();
                    writer.print("<" + elementName + ">");
                    writer.print(DateHelper.getGMTDateFormat("yyyy-MM-dd").format(dt) + "T" + DateHelper.getGMTDateFormat("HH:mm:ss").format(dt) + ".000Z");
                    writer.print("</" + elementName + ">");
                } else {
                    if (!serializer.omitNullField(f)) {
                        indent(true, indentLevel, writer);
                        writer.print("<" + elementName + "/>");
                    }
                }
            } else {
                if (value != null) {
                    indent(true, indentLevel, writer);
                    if (!value.toString().isEmpty()) {
                        writer.print("<" + elementName + ">");
                        writer.print(value);
                        writer.print("</" + elementName + ">");
                    } else {
                        writer.print("<" + elementName + "/>");
                    }
                } else {
                    if (!serializer.omitNullField(f)) {
                        indent(true, indentLevel, writer);
                        writer.print("<" + elementName + "/>");
                    }
                }
            }
        } else if (fieldType.isArray()) {
            if (value != null) {
                if (!serializer.flattenField(f)) {
                    indent(true, indentLevel, writer);
                    writer.print("<" + elementName + ">");
                    indentLevel++;
                }

                for (Object sub : (Object[])value) {
                    serializer.serializeTo(sub, itemName, null, indentLevel, writer);
                }

                if (!serializer.flattenField(f)) {
                    indentLevel--;
                    indent(true, indentLevel, writer);
                    writer.print("</" + elementName + ">");
                }
            } else {
                if (!serializer.omitNullField(f)) {
                    indent(true, indentLevel, writer);
                    writer.print("<" + elementName + "/>");
                }
            }
        } else if (Collection.class.isAssignableFrom(fieldType)) {
            if (value != null) {
                if (!serializer.flattenField(f)) {
                    indent(true, indentLevel, writer);
                    writer.print("<" + elementName + ">");
                    indentLevel++;
                }

                Iterator it = ((Collection)value).iterator();
                if (it != null) {
                    while (it.hasNext()) {
                        Object sub = it.next();
                        serializer.serializeTo(sub, itemName, null, indentLevel, writer);
                    }
                }

                if (!serializer.flattenField(f)) {
                    indentLevel--;
                    indent(true, indentLevel, writer);
                    writer.print("</" + elementName + ">");
                }
            } else {
                if (!serializer.omitNullField(f)) {
                    indent(true, indentLevel, writer);
                    writer.print("<" + elementName + "/>");
                }
            }
        } else {
            serializer.serializeTo(value, elementName, null, indentLevel, writer);
        }
    }

    @Override
    public void writeSeparator(int indentLevel, PrintWriter writer) {
        // do nothing
    }

    private void indent(boolean newLine, int indentLevel, PrintWriter writer) {
        if (newLine)
            writer.println("");
        for (int i = 0; i < indentLevel; i++)
            writer.append("    ");
    }
}
