/* FichothequeLib_API - Copyright (c) 2015-2023 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.exportation.transformation;

import java.text.ParseException;
import net.mapeadores.util.annotation.Nullable;
import net.mapeadores.util.text.StringUtils;
import net.mapeadores.util.text.ValidExtension;


/**
 *
 * @author Vincent Calame
 */
public final class TemplateKey implements Comparable<TemplateKey> {

    public final static String DEFAULT_NAME = "_default";
    public final static String FRAGMENT_NAME = "_fragment";
    public final static String CLEAN_NAME = "_clean";
    private final String key;
    private final TransformationKey transformationKey;
    private final ValidExtension extension;
    private final String name;
    private final boolean isDist;

    private TemplateKey(TransformationKey transformationKey) {
        this(transformationKey, null, DEFAULT_NAME);
    }

    private TemplateKey(TransformationKey transformationKey, ValidExtension extension) {
        this(transformationKey, extension, DEFAULT_NAME);
    }

    private TemplateKey(TransformationKey transformationKey, ValidExtension extension, String name) {
        this.transformationKey = transformationKey;
        this.extension = extension;
        this.name = name;
        this.isDist = isDist(name);
        if (extension == null) {
            this.key = transformationKey + "/" + name;
        } else {
            this.key = transformationKey + "/" + name + "." + extension;
        }
    }

    @Override
    public int hashCode() {
        return key.hashCode();
    }

    @Override
    public boolean equals(Object other) {
        if (other == null) {
            return false;
        }
        if (other == this) {
            return true;
        }
        if (other.getClass() != this.getClass()) {
            return false;
        }
        return (this.key.equals(((TemplateKey) other).key));
    }

    public String getKeyString() {
        return key;
    }

    @Override
    public String toString() {
        return key;
    }

    @Override
    public int compareTo(TemplateKey otherTemplateKey) {
        return this.key.compareTo(otherTemplateKey.key);
    }

    public boolean isDist() {
        return isDist;
    }

    public boolean isSimpleTemplate() {
        return (extension == null);
    }

    public boolean isStreamTemplate() {
        return (extension != null);
    }

    public TransformationKey getTransformationKey() {
        return transformationKey;
    }

    @Nullable
    public String getExtension() {
        if (extension != null) {
            return extension.toString();
        } else {
            return null;
        }
    }

    public ValidExtension getValidExtension() {
        return extension;
    }

    public String getName() {
        return name;
    }

    public String getCompleteName() {
        if (extension != null) {
            return getName() + "." + extension.toString();
        } else {
            return getName();
        }
    }

    public static TemplateKey parse(TransformationKey transformationKey, String name) throws ParseException {
        if (transformationKey == null) {
            throw new IllegalArgumentException("transformationKey is null");
        }
        return parse(transformationKey, null, name);
    }

    public static TemplateKey parse(TransformationKey transformationKey, ValidExtension extension, String name) throws ParseException {
        if (transformationKey == null) {
            throw new IllegalArgumentException("transformationKey is null");
        }
        name = checkTemplateName(name, extension);
        return new TemplateKey(transformationKey, extension, name);
    }

    public static TemplateKey parse(String keyString) throws ParseException {
        int idx = keyString.indexOf('/');
        if (idx == -1) {
            throw new ParseException("separator / is missing", 0);
        }
        TransformationKey transformationKey = TransformationKey.parse(keyString.substring(0, idx));
        String name = keyString.substring(idx + 1);
        if (name.length() == 0) {
            return new TemplateKey(transformationKey);
        }
        int pointIdx = name.indexOf('.');
        switch (pointIdx) {
            case -1:
                return parse(transformationKey, null, name);
            case 0: {
                ValidExtension validExtension = ValidExtension.parse(name.substring(1));
                return new TemplateKey(transformationKey, validExtension);
            }
            default: {
                ValidExtension validExtension = ValidExtension.parse(name.substring(pointIdx + 1));
                return parse(transformationKey, validExtension, name.substring(0, pointIdx));
            }
        }
    }


    public static TemplateKey toDefault(TransformationKey transformationKey) {
        return new TemplateKey(transformationKey);
    }

    public static TemplateKey toDefault(TransformationKey transformationKey, ValidExtension extension) {
        if (extension == null) {
            return new TemplateKey(transformationKey);
        } else {
            return new TemplateKey(transformationKey, extension);
        }
    }

    private static String checkTemplateName(String name, ValidExtension extension) throws ParseException {
        if ((name == null) || (name.isEmpty())) {
            return DEFAULT_NAME;
        }
        switch (name) {
            case DEFAULT_NAME:
                return DEFAULT_NAME;
            case FRAGMENT_NAME: {
                if (extension == null) {
                    return FRAGMENT_NAME;
                } else {
                    throw new ParseException("_fragment is not available for extension template", 0);
                }
            }
            case CLEAN_NAME: {
                if (extension == null) {
                    return CLEAN_NAME;
                } else {
                    throw new ParseException("_fragment is not available for extension template", 0);
                }
            }
            default:
                StringUtils.checkTechnicalName(name, true);
                return name;
        }
    }

    private static boolean isDist(String name) {
        return name.startsWith("_");
    }

}
