package org.jabref.gui.maintable;

import java.util.Optional;

import org.jabref.model.database.BibDatabase;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.AuthorList;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.Field;
import org.jabref.model.entry.field.FieldProperty;
import org.jabref.model.entry.field.OrFields;

import static org.jabref.gui.maintable.NameDisplayPreferences.AbbreviationStyle;
import static org.jabref.gui.maintable.NameDisplayPreferences.DisplayStyle;

public class MainTableFieldValueFormatter {
    private final DisplayStyle displayStyle;
    private final AbbreviationStyle abbreviationStyle;
    private final BibDatabase bibDatabase;

    public MainTableFieldValueFormatter(NameDisplayPreferences nameDisplayPreferences, BibDatabaseContext bibDatabaseContext) {
        this.displayStyle = nameDisplayPreferences.getDisplayStyle();
        this.abbreviationStyle = nameDisplayPreferences.getAbbreviationStyle();
        this.bibDatabase = bibDatabaseContext.getDatabase();
    }

    /**
     * Format fields for {@link BibEntryTableViewModel}, according to user preferences and with latex translated to
     * unicode if possible.
     *
     * @param fields the fields argument of {@link BibEntryTableViewModel#getFields(OrFields)}.
     * @param entry the BibEntry of {@link BibEntryTableViewModel}.
     * @return The formatted name field.
     */
    public String formatFieldsValues(final OrFields fields, final BibEntry entry) {
        for (Field field : fields.getFields()) {
            if (field.getProperties().contains(FieldProperty.PERSON_NAMES) && (displayStyle != DisplayStyle.AS_IS)) {
                Optional<String> name = entry.getResolvedFieldOrAlias(field, bibDatabase);

                if (name.isPresent()) {
                    return formatFieldWithAuthorValue(name.get());
                }
            } else {
                Optional<String> content = entry.getResolvedFieldOrAliasLatexFree(field, bibDatabase);

                if (content.isPresent()) {
                    return content.get();
                }
            }
        }
        return "";
    }

    /**
     * Format a name field for the table, according to user preferences and with latex expressions translated if
     * possible.
     *
     * @param nameToFormat The contents of the name field.
     * @return The formatted name field.
     */
    private String formatFieldWithAuthorValue(final String nameToFormat) {
        if (nameToFormat == null) {
            return null;
        }

        AuthorList authors = AuthorList.parse(nameToFormat);

        if (((displayStyle == DisplayStyle.FIRSTNAME_LASTNAME)
                || (displayStyle == DisplayStyle.LASTNAME_FIRSTNAME))
                && (abbreviationStyle == AbbreviationStyle.LASTNAME_ONLY)) {
            return authors.latexFree().getAsLastNames(false);
        }

        return switch (displayStyle) {
            default -> nameToFormat;
            case FIRSTNAME_LASTNAME -> authors.latexFree().getAsFirstLastNames(
                    abbreviationStyle == AbbreviationStyle.FULL,
                    false);
            case LASTNAME_FIRSTNAME -> authors.latexFree().getAsLastFirstNames(
                    abbreviationStyle == AbbreviationStyle.FULL,
                    false);
            case NATBIB -> authors.latexFree().getAsNatbib();
        };
    }
}
