/* ====================================================================
   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.
==================================================================== */

package org.apache.poi.hslf.record;

import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Supplier;

import org.apache.poi.common.usermodel.fonts.FontFamily;
import org.apache.poi.common.usermodel.fonts.FontPitch;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil;

/**
 * This atom corresponds exactly to a Windows Logical Font (LOGFONT) structure.
 * It keeps all the information needed to define the attributes of a font,
 * such as height, width, etc. For more information, consult the
 * Windows API Programmer's reference.
 *
 * @author Yegor Kozlov
 */

public final class FontEntityAtom extends RecordAtom {

    //arbitrarily selected; may need to increase
    private static final int MAX_RECORD_LENGTH = 1_000_000;

    private static final int[] FLAGS_MASKS = {
        0x0001, 0x0100, 0x0200, 0x0400, 0x0800
    };

    private static final String[] FLAGS_NAMES = {
        "EMBED_SUBSETTED",
        "RASTER_FONT",
        "DEVICE_FONT",
        "TRUETYPE_FONT",
        "NO_FONT_SUBSTITUTION"
    };

    /**
     * record header
     */
    private final byte[] _header;

	/**
     * record data
     */
	private byte[] _recdata;

    /**
     * Build an instance of <code>FontEntityAtom</code> from on-disk data
     */
	/* package */ FontEntityAtom(byte[] source, int start, int len) {
		// Get the header
        _header = Arrays.copyOfRange(source, start, start+8);

		// Grab the record data
		_recdata = IOUtils.safelyClone(source, start+8, len-8, MAX_RECORD_LENGTH);
	}

    /**
     * Create a new instance of <code>FontEntityAtom</code>
     */
    public FontEntityAtom() {
        _recdata = new byte[68];
        _header = new byte[8];

        LittleEndian.putShort(_header, 2, (short)getRecordType());
        LittleEndian.putInt(_header, 4, _recdata.length);
    }

    @Override
    public long getRecordType() {
        return RecordTypes.FontEntityAtom.typeID;
    }

    /**
     * A null-terminated string that specifies the typeface name of the font.
     * The length of this string must not exceed 32 characters
	 *  including the null terminator.
     * @return font name
     */
    public String getFontName(){
    	final int maxLen = Math.min(_recdata.length,64)/2;
    	return StringUtil.getFromUnicodeLE0Terminated(_recdata, 0, maxLen);
    }

    /**
     * Set the name of the font.
     * The length of this string must not exceed 32 characters
	 *  including the null terminator.
	 * Will be converted to null-terminated if not already
     * @param name of the font
     */
    public void setFontName(String name) {
        // Ensure it's not now too long
        int nameLen = name.length() + (name.endsWith("\u0000") ? 0 : 1);
        if (nameLen > 32) {
            throw new HSLFException("The length of the font name, including null termination, must not exceed 32 characters");
        }

        // Everything's happy, so save the name
        byte[] bytes = StringUtil.getToUnicodeLE(name);
        System.arraycopy(bytes, 0, _recdata, 0, bytes.length);
        // null the remaining bytes
        Arrays.fill(_recdata, bytes.length, 64, (byte)0);
    }

    public void setFontIndex(int idx){
        LittleEndian.putShort(_header, 0, (short)idx);
    }

    public int getFontIndex(){
        return LittleEndian.getShort(_header, 0) >> 4;
    }

    /**
     * set the character set
     *
     * @param charset - characterset
     */
    public void setCharSet(int charset){
        _recdata[64] = (byte)charset;
    }

    /**
     * get the character set
     *
     * @return charset - characterset
     */
    public int getCharSet(){
        return _recdata[64];
    }

    /**
     * set the font flags
     * Bit 1: If set, font is subsetted
     *
     * @param flags - the font flags
     */
    public void setFontFlags(int flags){
        _recdata[65] = (byte)flags;
    }

    /**
     * get the character set
     * Bit 1: If set, font is subsetted
     *
     * @return the font flags
     */
    public int getFontFlags(){
        return _recdata[65];
    }

    /**
     * set the font type
     * <p>
     * Bit 1: Raster Font
     * Bit 2: Device Font
     * Bit 3: TrueType Font
     * </p>
     *
     * @param type - the font type
     */
    public void setFontType(int type){
        _recdata[66] = (byte)type;
    }

    /**
     * get the font type
     * <p>
     * Bit 1: Raster Font
     * Bit 2: Device Font
     * Bit 3: TrueType Font
     * </p>
     *
     * @return the font type
     */
    public int getFontType(){
        return _recdata[66];
    }

    /**
     * set lfPitchAndFamily
     *
     *
     * @param val - Corresponds to the lfPitchAndFamily field of the Win32 API LOGFONT structure
     */
    public void setPitchAndFamily(int val){
        _recdata[67] = (byte)val;
    }

    /**
     * get lfPitchAndFamily
     *
     * @return corresponds to the lfPitchAndFamily field of the Win32 API LOGFONT structure
     */
    public int getPitchAndFamily(){
        return _recdata[67];
    }

    /**
	 * Write the contents of the record back, so it can be written to disk
	 */
	@Override
    public void writeOut(OutputStream out) throws IOException {
		out.write(_header);
		out.write(_recdata);
	}

    @Override
    public Map<String, Supplier<?>> getGenericProperties() {
        return GenericRecordUtil.getGenericProperties(
            "fontName", this::getFontName,
            "fontIndex", this::getFontIndex,
            "charset", this::getCharSet,
            "fontFlags", getBitsAsString(this::getFontFlags, FLAGS_MASKS, FLAGS_NAMES),
            "fontPitch", () -> FontPitch.valueOfPitchFamily((byte)getPitchAndFamily()),
            "fontFamily", () -> FontFamily.valueOfPitchFamily((byte)getPitchAndFamily())
        );
    }
}
