/* FichothequeLib_API - Copyright (c) 2006-2022 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.fichotheque.syntax;

import java.io.IOException;
import net.fichotheque.Fichotheque;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.fiche.EmailItem;
import net.fichotheque.corpus.fiche.DateItem;
import net.fichotheque.corpus.fiche.FicheItem;
import net.fichotheque.corpus.fiche.FicheItems;
import net.fichotheque.corpus.fiche.GeopointItem;
import net.fichotheque.corpus.fiche.ImageItem;
import net.fichotheque.corpus.fiche.Item;
import net.fichotheque.corpus.fiche.LanguageItem;
import net.fichotheque.corpus.fiche.LinkItem;
import net.fichotheque.corpus.fiche.AmountItem;
import net.fichotheque.corpus.fiche.NumberItem;
import net.fichotheque.corpus.fiche.ParaItem;
import net.fichotheque.corpus.fiche.CountryItem;
import net.fichotheque.corpus.fiche.PersonItem;
import net.fichotheque.sphere.Redacteur;
import net.fichotheque.utils.SphereUtils;
import net.mapeadores.util.models.PersonCore;
import net.mapeadores.util.primitives.DegreDecimal;
import net.mapeadores.util.text.SeparatorOptions;


/**
 *
 * @author Vincent Calame
 */
public final class FormSyntax {

    public static final SeparatorOptions DEFAULT_INLINE_SEPARATOROPTIONS = new SeparatorOptions(';', true, true);
    public static final SeparatorOptions DEFAULT_BLOCK_SEPARATOROPTIONS = new SeparatorOptions('\n', true, false);

    private FormSyntax() {
    }

    public static String toString(FicheItems ficheItems, Fichotheque fichotheque, SeparatorOptions separatorOptions, Parameters parameters) {
        int size = ficheItems.size();
        if (size == 0) {
            return "";
        }
        StringBuilder buf = new StringBuilder(128);
        for (int k = 0; k < size; k++) {
            FicheItem ficheItem = ficheItems.get(k);
            buf.append(toString(ficheItem, fichotheque, parameters));
            if (k < (size - 1)) {
                buf.append(separatorOptions.getSeparator());
                if (separatorOptions.isSpaceInclude()) {
                    buf.append(' ');
                }
            } else if (separatorOptions.isLastInclude()) {
                buf.append(separatorOptions.getSeparator());
                if (separatorOptions.isSpaceInclude()) {
                    buf.append(' ');
                }
            }
        }
        return buf.toString();
    }

    public static String toString(FicheItem item, Fichotheque fichotheque, Parameters parameters) {
        if (item instanceof Item) {
            return toString((Item) item);
        } else if (item instanceof PersonItem) {
            return toString((PersonItem) item, fichotheque, getDefaultSphereKey(parameters));
        } else if (item instanceof LanguageItem) {
            return toString((LanguageItem) item);
        } else if (item instanceof CountryItem) {
            return toString((CountryItem) item);
        } else if (item instanceof DateItem) {
            return toString((DateItem) item);
        } else if (item instanceof EmailItem) {
            return toString((EmailItem) item);
        } else if (item instanceof LinkItem) {
            return toString((LinkItem) item);
        } else if (item instanceof NumberItem) {
            return toString((NumberItem) item, getDecimalChar(parameters));
        } else if (item instanceof AmountItem) {
            return toString((AmountItem) item, getDecimalChar(parameters));
        } else if (item instanceof GeopointItem) {
            return toString((GeopointItem) item, getDecimalChar(parameters));
        } else if (item instanceof ParaItem) {
            return toString((ParaItem) item);
        } else if (item instanceof ImageItem) {
            return toString((ImageItem) item);
        } else {
            throw new IllegalArgumentException("unknown FicheItem implementation");
        }
    }

    public static String toString(DegreDecimal degreDecimal, Parameters parameters) {
        return degreDecimal.toDecimal().toStringWithBlank(getDecimalChar(parameters));
    }

    public static String toString(ParaItem para) {
        StringBuilder buf = new StringBuilder();
        try {
            FicheblockSyntax.appendTextContent(buf, para, true);
        } catch (IOException ioe) {
        }
        return buf.toString();
    }

    public static String toString(Item item) {
        String value = item.getValue();
        return escapeString(value);
    }

    public static String escapeString(String s) {
        StringBuilder buf = new StringBuilder(s.length() + 20);
        escapeString(buf, s);
        return buf.toString();
    }

    private static void escapeString(StringBuilder buf, String s) {
        try {
            escapeString((Appendable) buf, s);
        } catch (IOException ioe) {
        }
    }

    public static void escapeString(Appendable buf, String s) throws IOException {
        int length = s.length();
        for (int i = 0; i < length; i++) {
            char carac = s.charAt(i);
            switch (carac) {
                case '\u00A0':
                case '\u202F':
                    buf.append('~');
                    break;
                default:
                    buf.append(carac);

            }
        }
    }

    public static String toString(PersonItem personItem, Fichotheque fichotheque, SubsetKey defaultSphereKey) {
        String redacteurGlobalId = personItem.getRedacteurGlobalId();
        if (redacteurGlobalId != null) {
            Redacteur redacteur = SphereUtils.getRedacteur(fichotheque, redacteurGlobalId);
            if (redacteur != null) {
                if ((defaultSphereKey != null) && (defaultSphereKey.equals(redacteur.getSubsetKey()))) {
                    return redacteur.getLogin();
                } else {
                    return redacteur.getBracketStyle();
                }
            } else {
                return redacteurGlobalId;
            }
        } else {
            PersonCore personCore = personItem.getPersonCore();
            StringBuilder buf = new StringBuilder(64);
            escapeString(buf, personCore.getSurname());
            buf.append('*');
            if (personCore.isSurnameFirst()) {
                buf.append('%');
            }
            escapeString(buf, personCore.getForename());
            String organism = personItem.getOrganism();
            if (organism != null) {
                buf.append('*');
                escapeString(buf, organism);
            }
            return buf.toString();
        }
    }

    public static String toString(LanguageItem languageItem) {
        return languageItem.getLang().toString();
    }

    public static String toString(CountryItem countryItem) {
        return countryItem.getCountry().toString();
    }

    public static String toString(DateItem dateItem) {
        return dateItem.toString();
    }

    public static String toString(EmailItem emailItem) {
        return emailItem.toString();
    }

    public static String toString(LinkItem linkItem) {
        StringBuilder buf = new StringBuilder(128);
        String href = linkItem.getHref();
        buf.append(href);
        String title = linkItem.getTitle();
        if (title.length() == 0) {
            title = null;
        } else if (title.equals(href)) {
            title = null;
        } else if ((href.length() > 8) && (title.equals(href.substring(7)))) {
            title = null;
        } else {
            buf.append('*');
            escapeString(buf, title);
        }
        String comment = linkItem.getComment();
        if (comment.length() > 0) {
            if (title == null) {
                buf.append('*');
            }
            buf.append('*');
            escapeString(buf, comment);
        }
        return buf.toString();
    }

    public static String toString(ImageItem imageItem) {
        StringBuilder buf = new StringBuilder(128);
        String src = imageItem.getSrc();
        String alt = imageItem.getAlt();
        String title = imageItem.getTitle();
        buf.append(src);
        if (alt.length() > 0) {
            buf.append('*');
            escapeString(buf, alt);
        }
        if (title.length() > 0) {
            if (alt.length() == 0) {
                buf.append('*');
            }
            buf.append('*');
            escapeString(buf, alt);
        }
        return buf.toString();
    }

    public static String toString(NumberItem numberItem, char decimalChar) {
        String valString = numberItem.getDecimal().toStringWithBlank(decimalChar);
        return valString;
    }

    public static String toString(AmountItem amountItem, char decimalChar) {
        String valString = amountItem.getDecimal().toStringWithBlank(decimalChar);
        String cur = amountItem.getCurrency().getCurrencyCode();
        return valString + cur;
    }

    public static String toString(GeopointItem geopointItem, char decimalChar) {
        StringBuilder buf = new StringBuilder();
        buf.append(geopointItem.getLatitude().toDecimal().toStringWithBlank(decimalChar));
        buf.append("* ");
        buf.append(geopointItem.getLongitude().toDecimal().toStringWithBlank(decimalChar));
        return buf.toString();
    }


    public static Parameters parameters() {
        return new Parameters();
    }

    public static Parameters parameters(Parameters others) {
        return new Parameters(others);
    }

    private static char getDecimalChar(Parameters parameters) {
        if (parameters == null) {
            return '.';
        }
        return parameters.decimalChar();
    }

    private static SubsetKey getDefaultSphereKey(Parameters parameters) {
        if (parameters == null) {
            return null;
        }
        return parameters.defautSphereKey();
    }


    public static class Parameters {

        private SubsetKey defautSphereKey = null;
        private char decimalChar = '.';

        private Parameters() {
        }

        private Parameters(Parameters other) {
            this.decimalChar = other.decimalChar;
            this.defautSphereKey = other.defautSphereKey;
        }

        public SubsetKey defautSphereKey() {
            return defautSphereKey;
        }

        public Parameters defautSphereKey(SubsetKey defautSphereKey) {
            this.defautSphereKey = defautSphereKey;
            return this;
        }

        public char decimalChar() {
            return decimalChar;
        }

        public Parameters decimalChar(char decimalChar) {
            this.decimalChar = decimalChar;
            return this;
        }

    }

}
