/*
 *  Copyright (C) 2010-2013 JPEXS
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.jpexs.decompiler.flash.tags.base;

import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.tags.DefineText2Tag;
import com.jpexs.decompiler.flash.tags.DefineTextTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.types.GLYPHENTRY;
import com.jpexs.decompiler.flash.types.SHAPE;
import com.jpexs.decompiler.flash.types.TEXTRECORD;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphMetrics;
import java.awt.font.GlyphVector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 *
 * @author JPEXS
 */
public abstract class FontTag extends CharacterTag implements AloneTag {

    public FontTag(SWF swf, int id, String name, byte data[], long pos) {
        super(swf, id, name, data, pos);
    }

    public abstract int getFontId();

    public abstract List<SHAPE> getGlyphShapeTable();

    public abstract void addCharacter(List<Tag> tags, char character, String fontName);

    public abstract char glyphToChar(List<Tag> tags, int glyphIndex);

    public abstract int charToGlyph(List<Tag> tags, char c);

    public abstract int getGlyphAdvance(int glyphIndex);

    public abstract int getGlyphWidth(int glyphIndex);

    public abstract String getFontName(List<Tag> tags);

    public abstract boolean isSmall();

    public abstract boolean isBold();

    public abstract boolean isItalic();

    public abstract int getDivider();

    public abstract int getAscent();

    public abstract int getDescent();

    public abstract int getLeading();

    public boolean hasLayout() {
        return false;
    }

    public boolean containsChar(List<Tag> tags, char character) {
        return charToGlyph(tags, character) > -1;
    }

    public int getFontStyle() {
        int fontStyle = 0;
        if (isBold()) {
            fontStyle |= Font.BOLD;
        }
        if (isItalic()) {
            fontStyle |= Font.ITALIC;
        }
        return fontStyle;
    }

    public abstract String getCharacters(List<Tag> tags);

    @Override
    public String getName(List<Tag> tags) {
        String nameAppend = "";
        if (exportName != null) {
            nameAppend = ": " + exportName;
        }
        if (className != null) {
            nameAppend = ": " + className;
        }
        String fontName = getFontName(tags);
        if (fontName != null) {
            nameAppend = ": " + fontName;
        }
        return name + " (" + getCharacterId() + nameAppend + ")";
    }

    public static void shiftGlyphIndices(int fontId, int startIndex, List<Tag> tags) {
        List<TEXTRECORD> textRecords = new ArrayList<>();
        for (Tag t : tags) {
            if (t instanceof DefineTextTag) {
                textRecords.addAll(((DefineTextTag) t).textRecords);
            }
            if (t instanceof DefineText2Tag) {
                textRecords.addAll(((DefineText2Tag) t).textRecords);
            }
        }
        int curFontId = 0;
        for (TEXTRECORD tr : textRecords) {
            if (tr.styleFlagsHasFont) {
                curFontId = tr.fontId;
            }
            if (curFontId != fontId) {
                continue;
            }
            for (GLYPHENTRY en : tr.glyphEntries) {
                if (en == null) { //Currently edited
                    continue;
                }
                if (en.glyphIndex >= startIndex) {
                    en.glyphIndex++;
                }
            }
        }
    }

    public static int getSystemFontAdvance(String fontName, int fontStyle, int fontSize, char character) {
        return getSystemFontAdvance(new Font(fontName, fontStyle, fontSize), character);
    }

    public static int getSystemFontAdvance(Font aFont, char character) {
        GlyphVector gv = aFont.createGlyphVector(new FontRenderContext(aFont.getTransform(), true, true), "" + character);
        GlyphMetrics gm = gv.getGlyphMetrics(0);
        return Math.round(gm.getAdvanceX());
    }
    public static List<String> fontNames = Arrays.asList(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());

    public static String findInstalledFontName(String fontName) {
        if (fontNames.contains(fontName)) {
            return fontName;
        }
        if (fontName.contains("_")) {
            String beforeUnderscore = fontName.substring(0, fontName.indexOf("_"));
            if (fontNames.contains(beforeUnderscore)) {
                return beforeUnderscore;
            }
        }
        fontName = "Times New Roman";
        if (fontNames.contains(fontName)) {
            return fontName;
        }
        fontName = "Arial";
        if (fontNames.contains(fontName)) {
            return fontName;
        }
        return fontNames.get(0);
    }
}
