package org.jabref.logic.openoffice.style;

import java.util.Comparator;
import java.util.List;

import org.jabref.logic.bibtex.comparator.FieldComparator;
import org.jabref.logic.bibtex.comparator.FieldComparatorStack;
import org.jabref.model.database.BibDatabase;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.openoffice.style.CitationGroups;

public class OOProcess {

    static final Comparator<BibEntry> AUTHOR_YEAR_TITLE_COMPARATOR = makeAuthorYearTitleComparator();
    static final Comparator<BibEntry> YEAR_AUTHOR_TITLE_COMPARATOR = makeYearAuthorTitleComparator();

    private OOProcess() {
    }

    private static Comparator<BibEntry> makeAuthorYearTitleComparator() {
        List<Comparator<BibEntry>> ayt = List.of(new FieldComparator(StandardField.AUTHOR),
                new FieldComparator(StandardField.YEAR),
                new FieldComparator(StandardField.TITLE));
        return new FieldComparatorStack<>(ayt);
    }

    private static Comparator<BibEntry> makeYearAuthorTitleComparator() {
        List<Comparator<BibEntry>> yat = List.of(new FieldComparator(StandardField.YEAR),
                new FieldComparator(StandardField.AUTHOR),
                new FieldComparator(StandardField.TITLE));
        return new FieldComparatorStack<>(yat);
    }

    /// The comparator used to sort within a group of merged
    /// citations.
    ///
    /// The term used here is "multicite". The option controlling the
    /// order is "MultiCiteChronological" in style files.
    ///
    /// Yes, they are always sorted one way or another.
    public static Comparator<BibEntry> comparatorForMulticite(JStyle style) {
        if (style.getMultiCiteChronological()) {
            return OOProcess.YEAR_AUTHOR_TITLE_COMPARATOR;
        } else {
            return OOProcess.AUTHOR_YEAR_TITLE_COMPARATOR;
        }
    }

    /// Fill citationGroups.bibliography and cgs.citationGroupsUnordered//CitationMarker
    /// according to style.
    public static void produceCitationMarkers(CitationGroups citationGroups, List<BibDatabase> databases, JStyle style) {
        if (!citationGroups.hasGlobalOrder()) {
            throw new IllegalStateException("produceCitationMarkers: globalOrder is misssing in citationGroups");
        }

        citationGroups.lookupCitations(databases);
        citationGroups.imposeLocalOrder(comparatorForMulticite(style));

        // fill CitationGroup.citationMarker
        if (style.isCitationKeyCiteMarkers()) {
            OOProcessCitationKeyMarkers.produceCitationMarkers(citationGroups, style);
        } else if (style.isNumberEntries()) {
            OOProcessNumericMarkers.produceCitationMarkers(citationGroups, style);
        } else {
            OOProcessAuthorYearMarkers.produceCitationMarkers(citationGroups, style);
        }
    }
}
