package ru.yandex.webmaster3.core.semantic.semantic_document_parser.microformats.spec.instances;

import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import ru.yandex.webmaster3.core.semantic.semantic_document_parser.microformats.spec.MFProperty;
import ru.yandex.webmaster3.core.semantic.semantic_document_parser.microformats.spec.MFType;
import ru.yandex.webmaster3.core.semantic.semantic_document_parser.microformats.spec.Microformat;
import ru.yandex.webmaster3.core.semantic.semantic_document_parser.microformats.exceptions.InvalidActionException;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

@Slf4j
public class MicroformatsManager {

    private final Map<String, Microformat> microformats = new HashMap<String, Microformat>();

    public void addMicroformat(@NotNull final Microformat microformat) {
        try {
            if (microformat.isRoot() || !microformats.containsKey(microformat.getName())) {
                microformats.put(microformat.getName(), microformat);
            }
        } catch (InvalidActionException e) {
            log.error(e.getMessage(),e);
        }
    }

    public void addMicroformat(@NotNull final Microformat... microformats) {
        for (final Microformat microformat : microformats) {
            addMicroformat(microformat);
        }
    }

    @Nullable
    public Microformat get(@NotNull final String str) {
        return microformats.get(str.toLowerCase());
    }

    /**
     * Deprecated. It is now not for all instances
     *
     * @return
     */
    @Deprecated
    public static MicroformatsManager managerForAllInstances() {
        final MicroformatsManager res = new MicroformatsManager();
        res.addMicroformat(ru.yandex.webmaster3.core.semantic.semantic_document_parser.microformats.spec.instances.Adr.getInstance(), Email.getInstance(), Geo.getInstance(), HCard.getInstance(),
                N.getInstance(), Org.getInstance(), Tel.getInstance(), ItemForHReview.getInstance(),
                HReview.getInstance(), HResume.getInstance(), HRecipe.getInstance());
        return res;
    }

    public static MicroformatsManager managerForMFsAndIncluded(final Microformat... mfs) {
        final HashSet<Microformat> microformats = new HashSet<Microformat>();
        for (final Microformat mf : mfs) {
            getAllMFs(mf, microformats);
        }
        final MicroformatsManager result = new MicroformatsManager();
        result.addMicroformat(microformats.toArray(new Microformat[microformats.size()]));
        return result;
    }

    private static void getAllMFs(final Microformat mf, final HashSet<Microformat> microformats) {
        if (microformats.add(mf)) {
            try {
                for (final MFProperty property : mf.getProperties()) {
                    for (final MFType type : property.getPossibleTypes()) {
                        if (type instanceof Microformat) {
                            getAllMFs((Microformat) type, microformats);
                        }
                    }
                }
            } catch (InvalidActionException e) {
                // Can't be
            }
        }
    }
}
