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

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.common.Duplicatable;
import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;

/**
 * For a given run of characters, holds the properties (which could
 *  be paragraph properties or character properties).
 * Used to hold the number of characters affected, the list of active
 *  properties, and the indent level if required.
 */
public class TextPropCollection implements GenericRecord, Duplicatable {
    private static final Logger LOG = LogManager.getLogger(TextPropCollection.class);

    /** All the different kinds of paragraph properties we might handle */
    private static final TextProp[] paragraphTextPropTypes = {
        // TextProp order is according to 2.9.20 TextPFException,
        // bitmask order can be different
        new ParagraphFlagsTextProp(),
        new TextProp(2, 0x80, "bullet.char"),
        new TextProp(2, 0x10, "bullet.font"),
        new TextProp(2, 0x40, "bullet.size"),
        new TextProp(4, 0x20, "bullet.color"),
        new TextAlignmentProp(),
        new TextProp(2, 0x1000, "linespacing"),
        new TextProp(2, 0x2000, "spacebefore"),
        new TextProp(2, 0x4000, "spaceafter"),
        new TextProp(2, 0x100, "text.offset"), // left margin
        // 0x200 - Undefined and MUST be ignored
        new TextProp(2, 0x400, "bullet.offset"), // indent
        new TextProp(2, 0x8000, "defaultTabSize"),
        new HSLFTabStopPropCollection(), // tabstops size is variable!
        new FontAlignmentProp(),
        new WrapFlagsTextProp(),
        new TextProp(2, 0x200000, "textDirection"),
        // 0x400000 MUST be zero and MUST be ignored
        new TextProp(0, 0x800000, "bullet.blip"), // TODO: check size
        new TextProp(0, 0x1000000, "bullet.scheme"), // TODO: check size
        new TextProp(0, 0x2000000, "hasBulletScheme"), // TODO: check size
        // 0xFC000000 MUST be zero and MUST be ignored
    };

    /** All the different kinds of character properties we might handle */
    private static final TextProp[] characterTextPropTypes = new TextProp[] {
        new TextProp(0, 0x100000, "pp10ext"),
        new TextProp(0, 0x1000000, "newAsian.font.index"), // A bit that specifies whether the newEAFontRef field of the TextCFException10 structure that contains this CFMasks exists.
        new TextProp(0, 0x2000000, "cs.font.index"), // A bit that specifies whether the csFontRef field of the TextCFException10 structure that contains this CFMasks exists.
        new TextProp(0, 0x4000000, "pp11ext"), // A bit that specifies whether the pp11ext field of the TextCFException10 structure that contains this CFMasks exists.
        new CharFlagsTextProp(),
        new TextProp(2, 0x10000, "font.index"),
        new TextProp(2, 0x200000, "asian.font.index"),
        new TextProp(2, 0x400000, "ansi.font.index"),
        new TextProp(2, 0x800000, "symbol.font.index"),
        new TextProp(2, 0x20000, "font.size"),
        new TextProp(4, 0x40000, "font.color"),
        new TextProp(2, 0x80000, "superscript")
    };

    public enum TextPropType {
        paragraph, character
    }

    private int charactersCovered;

    // indentLevel is only valid for paragraph collection
    // if it's set to -1, it must be omitted - see 2.9.36 TextMasterStyleLevel
    private short indentLevel;
	private final Map<String,TextProp> textProps = new HashMap<>();
    private int maskSpecial;
    private final TextPropType textPropType;

    /**
     * Create a new collection of text properties (be they paragraph
     *  or character) which will be groked via a subsequent call to
     *  buildTextPropList().
     */
    public TextPropCollection(int charactersCovered, TextPropType textPropType) {
        this.charactersCovered = charactersCovered;
        this.textPropType = textPropType;
    }

    public TextPropCollection(TextPropCollection other) {
        charactersCovered = other.charactersCovered;
        indentLevel = other.indentLevel;
        maskSpecial = other.maskSpecial;
        textPropType = other.textPropType;
        other.textProps.forEach((k,v) -> textProps.put(k, v.copy()));
    }

    public int getSpecialMask() {
        return maskSpecial;
    }

	/** Fetch the number of characters this styling applies to */
	public int getCharactersCovered() {
	    return charactersCovered;
    }

	/** Fetch the TextProps that define this styling in the record order */
	public List<TextProp> getTextPropList() {
	    List<TextProp> orderedList = new ArrayList<>();
        for (TextProp potProp : getPotentialProperties()) {
            TextProp textProp = textProps.get(potProp.getName());
            if (textProp != null) {
                orderedList.add(textProp);
            }
        }
	    return orderedList;
    }

	/** Fetch the TextProp with this name, or null if it isn't present */
	@SuppressWarnings("unchecked")
    public final <T extends TextProp> T findByName(String textPropName) {
		return (T)textProps.get(textPropName);
	}

    @SuppressWarnings("unchecked")
	public final <T extends TextProp> T removeByName(String name) {
	    return (T)textProps.remove(name);
	}

	public final TextPropType getTextPropType() {
	    return textPropType;
	}

	private TextProp[] getPotentialProperties() {
	    return (textPropType == TextPropType.paragraph) ? paragraphTextPropTypes : characterTextPropTypes;
	}

	/**
	 * Checks the paragraph or character properties for the given property name.
	 * Throws a HSLFException, if the name doesn't belong into this set of properties
	 *
	 * @param name the property name
	 * @return if found, the property template to copy from
	 */
    @SuppressWarnings("unchecked")
	private <T extends TextProp> T validatePropName(final String name) {
       for (TextProp tp : getPotentialProperties()) {
            if (tp.getName().equals(name)) {
                return (T)tp;
            }
        }
       String errStr =
           "No TextProp with name " + name + " is defined to add from. " +
           "Character and paragraphs have their own properties/names.";
       throw new HSLFException(errStr);
	}

    /** Add the TextProp with this name to the list */
    @SuppressWarnings("unchecked")
    public final <T extends TextProp> T addWithName(final String name) {
        // Find the base TextProp to base on
        T existing = findByName(name);
        if (existing != null) return existing;

        // Add a copy of this property
        T textProp = (T)validatePropName(name).copy();
        textProps.put(name,textProp);
        return textProp;
    }

	/**
	 * Add the property at the correct position. Replaces an existing property with the same name.
	 *
	 * @param textProp the property to be added
	 */
	public final void addProp(TextProp textProp) {
	    if (textProp == null) {
	        throw new HSLFException("TextProp must not be null");
	    }

	    String propName = textProp.getName();
	    validatePropName(propName);

	    textProps.put(propName, textProp);
	}

	/**
	 * For an existing set of text properties, build the list of
	 *  properties coded for in a given run of properties.
	 * @return the number of bytes that were used encoding the properties list
	 */
	public int buildTextPropList(int containsField, byte[] data, int dataOffset) {
		int bytesPassed = 0;

		// For each possible entry, see if we match the mask
		// If we do, decode that, save it, and shuffle on
		for(TextProp tp : getPotentialProperties()) {
			// Check there's still data left to read

			// Check if this property is found in the mask
			if((containsField & tp.getMask()) != 0) {
                if(dataOffset+bytesPassed >= data.length) {
                    // Out of data, can't be any more properties to go
                    // remember the mask and return
                    maskSpecial |= tp.getMask();
                    return bytesPassed;
                }

				// Bingo, data contains this property
				TextProp prop = tp.copy();
				int val = 0;
				if (prop instanceof HSLFTabStopPropCollection) {
                    ((HSLFTabStopPropCollection)prop).parseProperty(data, dataOffset+bytesPassed);
                } else if (prop.getSize() == 2) {
					val = LittleEndian.getShort(data,dataOffset+bytesPassed);
				} else if(prop.getSize() == 4) {
					val = LittleEndian.getInt(data,dataOffset+bytesPassed);
				} else if (prop.getSize() == 0) {
                    //remember "special" bits.
                    maskSpecial |= tp.getMask();
                    continue;
                }

				if (prop instanceof BitMaskTextProp) {
				    ((BitMaskTextProp)prop).setValueWithMask(val, containsField);
				} else if (!(prop instanceof HSLFTabStopPropCollection)) {
				    prop.setValue(val);
				}
				bytesPassed += prop.getSize();
				addProp(prop);
			}
		}

		// Return how many bytes were used
		return bytesPassed;
	}

    /**
     * Clones the given text properties
     */
    @Override
	public TextPropCollection copy() {
        return new TextPropCollection(this);
	}

	/**
	 * Update the size of the text that this set of properties
	 *  applies to
	 */
	public void updateTextSize(int textSize) {
		charactersCovered = textSize;
	}

	   /**
     * Writes out to disk the header, and then all the properties
     */
    public void writeOut(OutputStream o) throws IOException {
        writeOut(o, false);
    }

	/**
	 * Writes out to disk the header, and then all the properties
	 */
	public void writeOut(OutputStream o, boolean isMasterStyle) throws IOException {
	    if (!isMasterStyle) {
	        // First goes the number of characters we affect
	        // MasterStyles don't have this field
            Record.writeLittleEndian(charactersCovered,o);
	    }

		// Then we have the indentLevel field if it's a paragraph collection
		if (textPropType == TextPropType.paragraph && indentLevel > -1) {
            Record.writeLittleEndian(indentLevel, o);
		}

		// Then the mask field
		int mask = maskSpecial;
		for (TextProp textProp : textProps.values()) {
            mask |= textProp.getWriteMask();
        }
        Record.writeLittleEndian(mask,o);

		// Then the contents of all the properties
		for (TextProp textProp : getTextPropList()) {
            int val = textProp.getValue();
            if (textProp instanceof BitMaskTextProp && textProp.getWriteMask() == 0) {
                // don't add empty properties, as they can't be recognized while reading
                continue;
            } else if (textProp.getSize() == 2) {
                Record.writeLittleEndian((short)val,o);
            } else if (textProp.getSize() == 4) {
                Record.writeLittleEndian(val,o);
            } else if (textProp instanceof HSLFTabStopPropCollection) {
                ((HSLFTabStopPropCollection)textProp).writeProperty(o);
            }
		}
	}

    public short getIndentLevel(){
        return indentLevel;
    }

    public void setIndentLevel(short indentLevel) {
        if (textPropType == TextPropType.character) {
            throw new RuntimeException("trying to set an indent on a character collection.");
        }
        this.indentLevel = indentLevel;
    }

    public int hashCode() {
	    return Objects.hash(charactersCovered,maskSpecial,indentLevel,textProps);
    }
    /**
     * compares most properties apart of the covered characters length
     */
    public boolean equals(Object other) {
        if (this == other) return true;
        if (other == null) return false;
        if (getClass() != other.getClass()) return false;

        TextPropCollection o = (TextPropCollection)other;
        if (o.maskSpecial != this.maskSpecial || o.indentLevel != this.indentLevel) {
            return false;
        }

        return textProps.equals(o.textProps);
    }

    public String toString() {
        StringBuilder out = new StringBuilder();
        out.append("  chars covered: " + getCharactersCovered());
        out.append("  special mask flags: 0x" + HexDump.toHex(getSpecialMask()) + "\n");
        if (textPropType == TextPropType.paragraph) {
            out.append("  indent level: "+getIndentLevel()+"\n");
        }
        for(TextProp p : getTextPropList()) {
            out.append("    ");
            out.append(p.toString());
            out.append("\n");
            if (p instanceof BitMaskTextProp) {
                BitMaskTextProp bm = (BitMaskTextProp)p;
                int i = 0;
                for (String s : bm.getSubPropNames()) {
                    if (bm.getSubPropMatches()[i]) {
                        out.append("          " + s + " = " + bm.getSubValue(i) + "\n");
                    }
                    i++;
                }
            }
        }

        out.append("  bytes that would be written: \n");

        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            writeOut(baos);
            byte[] b = baos.toByteArray();
            out.append(HexDump.dump(b, 0, 0));
        } catch (IOException e ) {
            LOG.atError().withThrowable(e).log("can't dump TextPropCollection");
        }

        return out.toString();
    }

    @Override
    public Map<String, Supplier<?>> getGenericProperties() {
        Map<String,Supplier<?>> m = new LinkedHashMap<>();
        m.put("charactersCovered", this::getCharactersCovered);
        m.put("indentLevel", this::getIndentLevel);
        textProps.forEach((s,t) -> m.put(s, () -> t));
        m.put("maskSpecial", this::getSpecialMask);
        m.put("textPropType", this::getTextPropType);
        return Collections.unmodifiableMap(m);
    }
}
