package ru.yandex.webmaster3.core.semantic.semantic_document_parser.microdata.data;

import ru.yandex.common.util.xml.Xmler;
import ru.yandex.webmaster3.core.semantic.semantic_document_parser.microdata.exceptions.MicrodataValidatorException;
import ru.yandex.webmaster3.core.semantic.semantic_document_parser.microdata.MicrodataUtils;
import ru.yandex.webmaster3.core.semantic.semantic_document_parser.serialize.util.APIVersion;

import java.util.*;
import java.util.regex.Pattern;

import static ru.yandex.common.util.xml.Xmler.attribute;
import static ru.yandex.common.util.xml.Xmler.tag;


/**
 * Created by IntelliJ IDEA.
 * User: rasifiel
 * Date: 7/31/11
 * Time: 1:18 AM
 * To change this template use File | Settings | File Templates.
 */
public class ComplexMicrodata extends Microdata {

    final LinkedHashMap<String, List<Microdata>> data = new LinkedHashMap<String, List<Microdata>>();
    private final String type;
    private final List<MicrodataValidatorException> exceptions = new ArrayList<MicrodataValidatorException>();

    public boolean noindex = false;
    public ComplexMicrodata(final String type) {
        if (type != null) {
            this.type = type.trim();
        } else {
            this.type = null;
        }
    }



    public void addException(final MicrodataValidatorException ex) {
        exceptions.add(ex);
    }

    public List<MicrodataValidatorException> getExceptions() {
        return Collections.unmodifiableList(exceptions);
    }

    public String toString() {
        return MicrodataUtils.MD2JSON(APIVersion.VERSION_1_0).apply(this).toString();
    }

    public Xmler.Tag toXmlTag() {
        final List<Xmler.Tag> tags = new LinkedList<Xmler.Tag>();
        for (final String key : data.keySet()) {
            for (final Microdata item : data.get(key)) {
                if (item instanceof ComplexMicrodata) {
                    tags.add(((ComplexMicrodata) item).toXmlTag(key));
                } else {
                    tags.add(tag(key, item.toString()));
                }
            }
        }
        return tag("item", attribute("href", getType()), tags);
    }

    public Xmler.Tag toXmlTag(final String rootName) {
        final List<Xmler.Tag> tags = new LinkedList<Xmler.Tag>();
        for (final String key : data.keySet()) {
            for (final Microdata item : data.get(key)) {
                if (item instanceof ComplexMicrodata) {
                    tags.add(((ComplexMicrodata) item).toXmlTag(key));
                } else {
                    tags.add(tag(key, item.toString()));
                }
            }
        }
        return tag(rootName, attribute("href", getType()), tags);
    }

    public String toXml() {
        final StringBuilder sb = new StringBuilder();
        toXmlTag().toXml(sb);
        return sb.toString();
    }

    final static Pattern WHITE_SPACE = Pattern.compile("\\s+");

    public void addPropValue(final String key, final Microdata value) {
        final String[] parts = WHITE_SPACE.split(key);
        for (final String part : parts) {
            final String lowerCasePart = part;
            if (!lowerCasePart.isEmpty()) {
                List<Microdata> propVal = data.get(lowerCasePart);
                if (propVal == null) {
                    propVal = new LinkedList<Microdata>();
                    data.put(lowerCasePart, propVal);
                }
                propVal.add(value);
            }
        }
    }

    public void addPropValue(final MicrodataProperty property) {
        addPropValue(property.name, property.data);
    }

    public List<Microdata> getPropAsList(final String rawKey) {
        final String key = rawKey;
        if (!data.containsKey(key)) {
            return Collections.emptyList();
        }
        return Collections.unmodifiableList(data.get(key));
    }

    public String getType() {
        return type;
    }

    public Set<String> getPropList() {
        return data.keySet();
    }

    public Microdata getFirst(final String key) {
        final List<Microdata> propData = getPropAsList(key);
        if (propData.isEmpty()) {
            return null;
        }
        return propData.get(0);
    }

    public String getFirstAsText(final String key) {
        final List<Microdata> propData = getPropAsList(key);
        if (propData.isEmpty()) {
            return null;
        }
        if (propData.get(0) instanceof TextMicrodata) {
            return propData.get(0).toString();
        } else {
            return null;
        }
    }

    public String forceFirstAsText(final String key) {
        final List<Microdata> propData = getPropAsList(key);
        if (propData.isEmpty()) {
            return null;
        }
        if (propData.get(0) instanceof TextMicrodata) {
            return ((TextMicrodata) propData.get(0)).toDataString();
        } else {
            return null;
        }
    }

    public String getFirstAsHtml(final String key) {
        final List<Microdata> propData = getPropAsList(key);
        if (propData.isEmpty()) {
            return null;
        }
        if (propData.get(0) instanceof TextMicrodata) {
            return ((TextMicrodata) propData.get(0)).html;
        } else {
            return null;
        }
    }

    public boolean isEmpty() {
        return data.isEmpty();
    }

}
