package ru.yandex.webmaster3.core.semantic.semantic_document_parser.rdfa.validator;

import ru.yandex.common.util.collections.Pair;
import ru.yandex.webmaster3.core.semantic.semantic_document_parser.microdata.MicrodataUtils;
import ru.yandex.webmaster3.core.semantic.semantic_document_parser.rdfa.data.RDFaEntity;
import ru.yandex.webmaster3.core.semantic.semantic_document_parser.rdfa.data.RDFaProperty;
import ru.yandex.webmaster3.core.semantic.semantic_document_parser.rdfa.data.RDFaValueProperty;
import ru.yandex.webmaster3.core.semantic.semantic_document_parser.rdfa.exceptions.OGPFieldsRDFaException;
import ru.yandex.webmaster3.core.semantic.semantic_document_parser.rdfa.exceptions.RDFaException;

import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Created by IntelliJ IDEA.
 * User: rasifiel
 * Date: 12.09.12
 * Time: 20:12
 */
public class OGPFieldsRDFaValidator implements RDFaValidator {

    public static final String HTTP_OGP_ME_NS = "http://ogp.me/ns#";
    private final List<String> fields;

    public OGPFieldsRDFaValidator(final List<String> fields) {
        this.fields = fields;
    }

    private static Pattern OGP_PROTOCOL_PATTERN = Pattern.compile("https?://ogp.me/ns#.*");

    @Override
    public List<RDFaException> validate(final RDFaEntity data) {
        final List<RDFaException> exceptions = new LinkedList<>();
        if (data.isRoot && isOgEntity(data)) {

            final List<Pair<String, RDFaEntity>> missingFields = new LinkedList<>();

            for (final String field : fields) {
                boolean foundField = false;
                for (String ogprefix : MicrodataUtils.protocolAliases(HTTP_OGP_ME_NS)) {
                    if (data.hasProperty(ogprefix + field)) {

                        foundField = true;
                        break;
                    }
                }
                if (!foundField) {
                    missingFields.add(new Pair<>(HTTP_OGP_ME_NS + field, data));
                }
            }

            if (!missingFields.isEmpty()) {
                StringBuilder resultBuilder = new StringBuilder();
                for (final Pair<String, RDFaEntity> field : missingFields) {
                    if (resultBuilder.length() == 0) {
                        resultBuilder.append(field.first);
                    } else {
                        resultBuilder.append(", ").append(field.first);
                    }
                }
                exceptions.add(
                        new OGPFieldsRDFaException(
                                true,
                                missingFields.get(0).second,
                                resultBuilder.toString(),
                                data.getLocation()
                        ));
            }
        }
        return exceptions;
    }

    private boolean isOgEntity(RDFaEntity data) {
        if (data.hasProperty("@type")) {
            List<RDFaProperty> properties = data.getProperty("@type");
            return properties.size() > 0 &&
                    properties.get(0) instanceof RDFaValueProperty &&
                    "og".equals(((RDFaValueProperty) properties.get(0)).getValue());
        } else {
            for (final String field : data.getPropertyList()) {
                if (OGP_PROTOCOL_PATTERN.matcher(field).matches()) {
                    return true;
                }
            }
        }
        return false;
    }
}
