/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* $Id$ */

package org.apache.fop.fonts;

import java.nio.CharBuffer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

// CSOFF: InnerAssignmentCheck
// CSOFF: LineLengthCheck

/**
 * The <code>GlyphDefinitionTable</code> class is a glyph table that implements
 * glyph definition functionality according to the OpenType GDEF table.
 * @author Glenn Adams
 */
public class GlyphDefinitionTable extends GlyphTable {

    /** logging instance */
    private static final Log log = LogFactory.getLog(GlyphDefinitionTable.class);                                       // CSOK: ConstantNameCheck

    /** glyph class subtable type */
    public static final int GDEF_LOOKUP_TYPE_GLYPH_CLASS = 1;
    /** attachment point subtable type */
    public static final int GDEF_LOOKUP_TYPE_ATTACHMENT_POINT = 2;
    /** ligature caret subtable type */
    public static final int GDEF_LOOKUP_TYPE_LIGATURE_CARET = 3;
    /** mark attachment subtable type */
    public static final int GDEF_LOOKUP_TYPE_MARK_ATTACHMENT = 4;

    /** pre-defined glyph class - base glyph */
    public static final int GLYPH_CLASS_BASE = 1;
    /** pre-defined glyph class - ligature glyph */
    public static final int GLYPH_CLASS_LIGATURE = 2;
    /** pre-defined glyph class - mark glyph */
    public static final int GLYPH_CLASS_MARK = 3;
    /** pre-defined glyph class - component glyph */
    public static final int GLYPH_CLASS_COMPONENT = 4;

    /** singleton glyph class table */
    private GlyphClassSubtable gct;
    /** singleton attachment point table */
    // private AttachmentPointSubtable apt;
    /** singleton ligature caret table */
    // private LigatureCaretSubtable lct;
    /** singleton mark attachment table */
    // private MarkAttachmentSubtable mat;

    /**
     * Instantiate a <code>GlyphDefinitionTable</code> object using the specified subtables.
     * @param subtables a list of identified subtables
     */
    public GlyphDefinitionTable ( List subtables ) {
        super ( null, new HashMap(0) );
        if ( ( subtables == null ) || ( subtables.size() == 0 ) ) {
            throw new AdvancedTypographicTableFormatException ( "subtables must be non-empty" );
        } else {
            for ( Iterator it = subtables.iterator(); it.hasNext();) {
                Object o = it.next();
                if ( o instanceof GlyphDefinitionSubtable ) {
                    addSubtable ( (GlyphSubtable) o );
                } else {
                    throw new AdvancedTypographicTableFormatException ( "subtable must be a glyph definition subtable" );
                }
            }
            freezeSubtables();
        }
    }

    /**
     * Reorder combining marks in glyph sequence so that they precede (within the sequence) the base
     * character to which they are applied. N.B. In the case of LTR segments, marks are not reordered by this,
     * method since when the segment is reversed by BIDI processing, marks are automatically reordered to precede
     * their base glyph.
     * @param gs an input glyph sequence
     * @param gpa associated glyph position adjustments (also reordered)
     * @param script a script identifier
     * @param language a language identifier
     * @return the reordered (output) glyph sequence
     */
    public GlyphSequence reorderCombiningMarks ( GlyphSequence gs, int[][] gpa, String script, String language ) {
        ScriptProcessor sp = ScriptProcessor.getInstance ( script );
        return sp.reorderCombiningMarks ( this, gs, gpa, script, language );
    }

    /** {@inheritDoc} */
    protected void addSubtable ( GlyphSubtable subtable ) {
        if ( subtable instanceof GlyphClassSubtable ) {
            this.gct = (GlyphClassSubtable) subtable;
        } else if ( subtable instanceof AttachmentPointSubtable ) {
            // TODO - not yet used
            // this.apt = (AttachmentPointSubtable) subtable;
        } else if ( subtable instanceof LigatureCaretSubtable ) {
            // TODO - not yet used
            // this.lct = (LigatureCaretSubtable) subtable;
        } else if ( subtable instanceof MarkAttachmentSubtable ) {
            // TODO - not yet used
            // this.mat = (MarkAttachmentSubtable) subtable;
        } else {
            throw new UnsupportedOperationException ( "unsupported glyph definition subtable type: " + subtable );
        }
    }

    /**
     * Determine if glyph belongs to pre-defined glyph class.
     * @param gid a glyph identifier (index)
     * @param gc a pre-defined glyph class (GLYPH_CLASS_BASE|GLYPH_CLASS_LIGATURE|GLYPH_CLASS_MARK|GLYPH_CLASS_COMPONENT).
     * @return true if glyph belongs to specified glyph class
     */
    public boolean isGlyphClass ( int gid, int gc ) {
        if ( gct != null ) {
            return gct.isGlyphClass ( gid, gc );
        } else {
            return false;
        }
    }

    /**
     * Determine glyph class.
     * @param gid a glyph identifier (index)
     * @return a pre-defined glyph class (GLYPH_CLASS_BASE|GLYPH_CLASS_LIGATURE|GLYPH_CLASS_MARK|GLYPH_CLASS_COMPONENT). 
     */
    public int getGlyphClass ( int gid ) {
        if ( gct != null ) {
            return gct.getGlyphClass ( gid );
        } else {
            return -1;
        }
    }

    /**
     * Map a lookup type name to its constant (integer) value.
     * @param name lookup type name
     * @return lookup type
     */
    public static int getLookupTypeFromName ( String name ) {
        int t;
        String s = name.toLowerCase();
        if ( "glyphclass".equals ( s ) ) {
            t = GDEF_LOOKUP_TYPE_GLYPH_CLASS;
        } else if ( "attachmentpoint".equals ( s ) ) {
            t = GDEF_LOOKUP_TYPE_ATTACHMENT_POINT;
        } else if ( "ligaturecaret".equals ( s ) ) {
            t = GDEF_LOOKUP_TYPE_LIGATURE_CARET;
        } else if ( "markattachment".equals ( s ) ) {
            t = GDEF_LOOKUP_TYPE_MARK_ATTACHMENT;
        } else {
            t = -1;
        }
        return t;
    }

    /**
     * Map a lookup type constant (integer) value to its name.
     * @param type lookup type
     * @return lookup type name
     */
    public static String getLookupTypeName ( int type ) {
        String tn = null;
        switch ( type ) {
        case GDEF_LOOKUP_TYPE_GLYPH_CLASS:
            tn = "glyphclass";
            break;
        case GDEF_LOOKUP_TYPE_ATTACHMENT_POINT:
            tn = "attachmentpoint";
            break;
        case GDEF_LOOKUP_TYPE_LIGATURE_CARET:
            tn = "ligaturecaret";
            break;
        case GDEF_LOOKUP_TYPE_MARK_ATTACHMENT:
            tn = "markattachment";
            break;
        default:
            tn = "unknown";
            break;
        }
        return tn;
    }

    /**
     * Create a definition subtable according to the specified arguments.
     * @param type subtable type
     * @param id subtable identifier
     * @param sequence subtable sequence
     * @param flags subtable flags (must be zero)
     * @param format subtable format
     * @param mapping subtable mapping table
     * @param entries subtable entries
     * @return a glyph subtable instance
     */
    public static GlyphSubtable createSubtable ( int type, String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
        GlyphSubtable st = null;
        switch ( type ) {
        case GDEF_LOOKUP_TYPE_GLYPH_CLASS:
            st = GlyphClassSubtable.create ( id, sequence, flags, format, mapping, entries );
            break;
        case GDEF_LOOKUP_TYPE_ATTACHMENT_POINT:
            st = AttachmentPointSubtable.create ( id, sequence, flags, format, mapping, entries );
            break;
        case GDEF_LOOKUP_TYPE_LIGATURE_CARET:
            st = LigatureCaretSubtable.create ( id, sequence, flags, format, mapping, entries );
            break;
        case GDEF_LOOKUP_TYPE_MARK_ATTACHMENT:
            st = MarkAttachmentSubtable.create ( id, sequence, flags, format, mapping, entries );
            break;
        default:
            break;
        }
        return st;
    }

    private abstract static class GlyphClassSubtable extends GlyphDefinitionSubtable {
        GlyphClassSubtable ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
            super ( id, sequence, flags, format, mapping );
        }
        /** {@inheritDoc} */
        public int getType() {
            return GDEF_LOOKUP_TYPE_GLYPH_CLASS;
        }
        /**
         * Determine if glyph belongs to pre-defined glyph class.
         * @param gid a glyph identifier (index)
         * @param gc a pre-defined glyph class (GLYPH_CLASS_BASE|GLYPH_CLASS_LIGATURE|GLYPH_CLASS_MARK|GLYPH_CLASS_COMPONENT).
         * @return true if glyph belongs to specified glyph class
         */
        public abstract boolean isGlyphClass ( int gid, int gc );
        /**
         * Determine glyph class.
         * @param gid a glyph identifier (index)
         * @return a pre-defined glyph class (GLYPH_CLASS_BASE|GLYPH_CLASS_LIGATURE|GLYPH_CLASS_MARK|GLYPH_CLASS_COMPONENT).
         */
        public abstract int getGlyphClass ( int gid );
        static GlyphDefinitionSubtable create ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
            if ( format == 1 ) {
                return new GlyphClassSubtableFormat1 ( id, sequence, flags, format, mapping, entries );
            } else {
                throw new UnsupportedOperationException();
            }
        }
    }

    private static class GlyphClassSubtableFormat1 extends GlyphClassSubtable {
        GlyphClassSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
            super ( id, sequence, flags, format, mapping, entries );
        }
        /** {@inheritDoc} */
        public List getEntries() {
            return null;
        }
        /** {@inheritDoc} */
        public boolean isCompatible ( GlyphSubtable subtable ) {
            return subtable instanceof GlyphClassSubtable;
        }
        /** {@inheritDoc} */
        public boolean isGlyphClass ( int gid, int gc ) {
            GlyphClassMapping cm = getClasses();
            if ( cm != null ) {
                return cm.getClassIndex ( gid, 0 ) == gc;
            } else {
                return false;
            }
        }
        /** {@inheritDoc} */
        public int getGlyphClass ( int gid ) {
            GlyphClassMapping cm = getClasses();
            if ( cm != null ) {
                return cm.getClassIndex ( gid, 0 );
            } else {
                return -1;
            }
        }
    }

    private abstract static class AttachmentPointSubtable extends GlyphDefinitionSubtable {
        AttachmentPointSubtable ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
            super ( id, sequence, flags, format, mapping );
        }
        /** {@inheritDoc} */
        public int getType() {
            return GDEF_LOOKUP_TYPE_ATTACHMENT_POINT;
        }
        static GlyphDefinitionSubtable create ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
            if ( format == 1 ) {
                return new AttachmentPointSubtableFormat1 ( id, sequence, flags, format, mapping, entries );
            } else {
                throw new UnsupportedOperationException();
            }
        }
    }

    private static class AttachmentPointSubtableFormat1 extends AttachmentPointSubtable {
        AttachmentPointSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
            super ( id, sequence, flags, format, mapping, entries );
        }
        /** {@inheritDoc} */
        public List getEntries() {
            return null;
        }
        /** {@inheritDoc} */
        public boolean isCompatible ( GlyphSubtable subtable ) {
            return subtable instanceof AttachmentPointSubtable;
        }
    }

    private abstract static class LigatureCaretSubtable extends GlyphDefinitionSubtable {
        LigatureCaretSubtable ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
            super ( id, sequence, flags, format, mapping );
        }
        /** {@inheritDoc} */
        public int getType() {
            return GDEF_LOOKUP_TYPE_LIGATURE_CARET;
        }
        static GlyphDefinitionSubtable create ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
            if ( format == 1 ) {
                return new LigatureCaretSubtableFormat1 ( id, sequence, flags, format, mapping, entries );
            } else {
                throw new UnsupportedOperationException();
            }
        }
    }

    private static class LigatureCaretSubtableFormat1 extends LigatureCaretSubtable {
        LigatureCaretSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
            super ( id, sequence, flags, format, mapping, entries );
        }
        /** {@inheritDoc} */
        public List getEntries() {
            return null;
        }
        /** {@inheritDoc} */
        public boolean isCompatible ( GlyphSubtable subtable ) {
            return subtable instanceof LigatureCaretSubtable;
        }
    }

    private abstract static class MarkAttachmentSubtable extends GlyphDefinitionSubtable {
        MarkAttachmentSubtable ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
            super ( id, sequence, flags, format, mapping );
        }
        /** {@inheritDoc} */
        public int getType() {
            return GDEF_LOOKUP_TYPE_MARK_ATTACHMENT;
        }
        static GlyphDefinitionSubtable create ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
            if ( format == 1 ) {
                return new MarkAttachmentSubtableFormat1 ( id, sequence, flags, format, mapping, entries );
            } else {
                throw new UnsupportedOperationException();
            }
        }
    }

    private static class MarkAttachmentSubtableFormat1 extends MarkAttachmentSubtable {
        MarkAttachmentSubtableFormat1 ( String id, int sequence, int flags, int format, GlyphMappingTable mapping, List entries ) {
            super ( id, sequence, flags, format, mapping, entries );
        }
        /** {@inheritDoc} */
        public List getEntries() {
            return null;
        }
        /** {@inheritDoc} */
        public boolean isCompatible ( GlyphSubtable subtable ) {
            return subtable instanceof MarkAttachmentSubtable;
        }
    }

}
