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

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Supplier;

import org.apache.poi.hssf.record.cont.ContinuableRecord;
import org.apache.poi.hssf.record.cont.ContinuableRecordOutput;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.ss.formula.ptg.OperandPtg;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.RecordFormatException;

/**
 * The TXO record (0x01B6) is used to define the properties of a text box. It is
 * followed by two or more continue records unless there is no actual text. The
 * first continue records contain the text data and the last continue record
 * contains the formatting runs.
 */
public final class TextObjectRecord extends ContinuableRecord {
	public static final short sid = 0x01B6;

	private static final int FORMAT_RUN_ENCODED_SIZE = 8; // 2 shorts and 4 bytes reserved

	private static final BitField HorizontalTextAlignment = BitFieldFactory.getInstance(0x000E);
	private static final BitField VerticalTextAlignment = BitFieldFactory.getInstance(0x0070);
	private static final BitField textLocked = BitFieldFactory.getInstance(0x0200);

	public static final short HORIZONTAL_TEXT_ALIGNMENT_LEFT_ALIGNED = 1;
	public static final short HORIZONTAL_TEXT_ALIGNMENT_CENTERED = 2;
	public static final short HORIZONTAL_TEXT_ALIGNMENT_RIGHT_ALIGNED = 3;
	public static final short HORIZONTAL_TEXT_ALIGNMENT_JUSTIFIED = 4;
	public static final short VERTICAL_TEXT_ALIGNMENT_TOP = 1;
	public static final short VERTICAL_TEXT_ALIGNMENT_CENTER = 2;
	public static final short VERTICAL_TEXT_ALIGNMENT_BOTTOM = 3;
	public static final short VERTICAL_TEXT_ALIGNMENT_JUSTIFY = 4;

	public static final short TEXT_ORIENTATION_NONE = 0;
	public static final short TEXT_ORIENTATION_TOP_TO_BOTTOM = 1;
	public static final short TEXT_ORIENTATION_ROT_RIGHT = 2;
	public static final short TEXT_ORIENTATION_ROT_LEFT = 3;

	private int field_1_options;
	private int field_2_textOrientation;
	private int field_3_reserved4;
	private int field_4_reserved5;
	private int field_5_reserved6;
	private int field_8_reserved7;

	private HSSFRichTextString _text;

	/*
	 * Note - the next three fields are very similar to those on
	 * EmbededObjectRefSubRecord(ftPictFmla 0x0009)
	 *
	 * some observed values for the 4 bytes preceding the formula: C0 5E 86 03
	 * C0 11 AC 02 80 F1 8A 03 D4 F0 8A 03
	 */
	private int _unknownPreFormulaInt;
	/** expect tRef, tRef3D, tArea, tArea3D or tName */
	private OperandPtg _linkRefPtg;
	/**
	 * Not clear if needed .  Excel seems to be OK if this byte is not present.
	 * Value is often the same as the earlier firstColumn byte. */
	private Byte _unknownPostFormulaByte;

	public TextObjectRecord() {}

	public TextObjectRecord(TextObjectRecord other) {
		super(other);
		field_1_options = other.field_1_options;
		field_2_textOrientation = other.field_2_textOrientation;
		field_3_reserved4 = other.field_3_reserved4;
		field_4_reserved5 = other.field_4_reserved5;
		field_5_reserved6 = other.field_5_reserved6;
		field_8_reserved7 = other.field_8_reserved7;

		_text = other._text;

		if (other._linkRefPtg != null) {
			_unknownPreFormulaInt = other._unknownPreFormulaInt;
			_linkRefPtg = other._linkRefPtg.copy();
			_unknownPostFormulaByte = other._unknownPostFormulaByte;
		}
	}

	public TextObjectRecord(RecordInputStream in) {
		field_1_options = in.readUShort();
		field_2_textOrientation = in.readUShort();
		field_3_reserved4 = in.readUShort();
		field_4_reserved5 = in.readUShort();
		field_5_reserved6 = in.readUShort();
		int field_6_textLength = in.readUShort();
		int field_7_formattingDataLength = in.readUShort();
		field_8_reserved7 = in.readInt();

		if (in.remaining() > 0) {
			// Text Objects can have simple reference formulas
			// (This bit not mentioned in the MS document)
			if (in.remaining() < 11) {
				throw new RecordFormatException("Not enough remaining data for a link formula");
			}
			int formulaSize = in.readUShort();
			_unknownPreFormulaInt = in.readInt();
			Ptg[] ptgs = Ptg.readTokens(formulaSize, in);
			if (ptgs.length != 1) {
				throw new RecordFormatException("Read " + ptgs.length
						+ " tokens but expected exactly 1");
			}
			_linkRefPtg = (OperandPtg) ptgs[0];
			_unknownPostFormulaByte = in.remaining() > 0 ? in.readByte() : null;
		} else {
			_linkRefPtg = null;
		}
		if (in.remaining() > 0) {
			throw new RecordFormatException("Unused " + in.remaining() + " bytes at end of record");
		}

		String text;
		if (field_6_textLength > 0) {
			text = readRawString(in, field_6_textLength);
		} else {
			text = "";
		}
		_text = new HSSFRichTextString(text);

		if (field_7_formattingDataLength > 0) {
			processFontRuns(in, _text, field_7_formattingDataLength);
		}
	}

	private static String readRawString(RecordInputStream in, int textLength) {
		byte compressByte = in.readByte();
		boolean isCompressed = (compressByte & 0x01) == 0;
		if (isCompressed) {
			return in.readCompressedUnicode(textLength);
		}
		return in.readUnicodeLEString(textLength);
	}

	private static void processFontRuns(RecordInputStream in, HSSFRichTextString str,
			int formattingRunDataLength) {
		if (formattingRunDataLength % FORMAT_RUN_ENCODED_SIZE != 0) {
			throw new RecordFormatException("Bad format run data length " + formattingRunDataLength
					+ ")");
		}
		int nRuns = formattingRunDataLength / FORMAT_RUN_ENCODED_SIZE;
		for (int i = 0; i < nRuns; i++) {
			short index = in.readShort();
			short iFont = in.readShort();
			in.readInt(); // skip reserved.
			str.applyFont(index, str.length(), iFont);
		}
	}

	public short getSid() {
		return sid;
	}

	private void serializeTXORecord(ContinuableRecordOutput out) {

		out.writeShort(field_1_options);
		out.writeShort(field_2_textOrientation);
		out.writeShort(field_3_reserved4);
		out.writeShort(field_4_reserved5);
		out.writeShort(field_5_reserved6);
		out.writeShort(_text.length());
		out.writeShort(getFormattingDataLength());
		out.writeInt(field_8_reserved7);

		if (_linkRefPtg != null) {
			int formulaSize = _linkRefPtg.getSize();
			out.writeShort(formulaSize);
			out.writeInt(_unknownPreFormulaInt);
			_linkRefPtg.write(out);
			if (_unknownPostFormulaByte != null) {
				out.writeByte(_unknownPostFormulaByte);
			}
		}
	}

	private void serializeTrailingRecords(ContinuableRecordOutput out) {
		out.writeContinue();
		out.writeStringData(_text.getString());
		out.writeContinue();
		writeFormatData(out, _text);
	}

	protected void serialize(ContinuableRecordOutput out) {

		serializeTXORecord(out);
		if (_text.getString().length() > 0) {
			serializeTrailingRecords(out);
		}
	}

	private int getFormattingDataLength() {
		if (_text.length() < 1) {
			// important - no formatting data if text is empty
			return 0;
		}
		return (_text.numFormattingRuns() + 1) * FORMAT_RUN_ENCODED_SIZE;
	}

	private static void writeFormatData(ContinuableRecordOutput out , HSSFRichTextString str) {
		int nRuns = str.numFormattingRuns();
		for (int i = 0; i < nRuns; i++) {
			out.writeShort(str.getIndexOfFormattingRun(i));
			int fontIndex = str.getFontOfFormattingRun(i);
			out.writeShort(fontIndex == HSSFRichTextString.NO_FONT ? 0 : fontIndex);
			out.writeInt(0); // skip reserved
		}
		out.writeShort(str.length());
		out.writeShort(0);
		out.writeInt(0); // skip reserved
	}

	/**
	 * Sets the Horizontal text alignment field value.
	 *
	 * @param value The horizontal alignment, use one of the HORIZONTAL_TEXT_ALIGNMENT_... constants in this class
	 */
	public void setHorizontalTextAlignment(int value) {
		field_1_options = HorizontalTextAlignment.setValue(field_1_options, value);
	}

	/**
	 * @return the Horizontal text alignment field value.
	 */
	public int getHorizontalTextAlignment() {
		return HorizontalTextAlignment.getValue(field_1_options);
	}

	/**
	 * Sets the Vertical text alignment field value.
	 *
	 * @param value The vertical alignment, use one of the VERTIUCAL_TEST_ALIGNMENT_... constants in this class
	 */
	public void setVerticalTextAlignment(int value) {
		field_1_options = VerticalTextAlignment.setValue(field_1_options, value);
	}

	/**
	 * @return the Vertical text alignment field value.
	 */
	public int getVerticalTextAlignment() {
		return VerticalTextAlignment.getValue(field_1_options);
	}

	/**
	 * Sets the text locked field value.
	 *
	 * @param value If the text should be locked
	 */
	public void setTextLocked(boolean value) {
		field_1_options = textLocked.setBoolean(field_1_options, value);
	}

	/**
	 * @return the text locked field value.
	 */
	public boolean isTextLocked() {
		return textLocked.isSet(field_1_options);
	}

	/**
	 * Get the text orientation field for the TextObjectBase record.
	 *
	 * @return One of TEXT_ORIENTATION_NONE TEXT_ORIENTATION_TOP_TO_BOTTOM
	 *         TEXT_ORIENTATION_ROT_RIGHT TEXT_ORIENTATION_ROT_LEFT
	 */
	public int getTextOrientation() {
		return field_2_textOrientation;
	}

	/**
	 * Set the text orientation field for the TextObjectBase record.
	 *
	 * @param textOrientation
	 *            One of TEXT_ORIENTATION_NONE TEXT_ORIENTATION_TOP_TO_BOTTOM
	 *            TEXT_ORIENTATION_ROT_RIGHT TEXT_ORIENTATION_ROT_LEFT
	 */
	public void setTextOrientation(int textOrientation) {
		this.field_2_textOrientation = textOrientation;
	}

	public HSSFRichTextString getStr() {
		return _text;
	}

	public void setStr(HSSFRichTextString str) {
		_text = str;
	}

	public Ptg getLinkRefPtg() {
		return _linkRefPtg;
	}

	@Override
	public TextObjectRecord copy() {
		return new TextObjectRecord(this);
	}

	@Override
	public HSSFRecordTypes getGenericRecordType() {
		return HSSFRecordTypes.TEXT_OBJECT;
	}

	@Override
	public Map<String, Supplier<?>> getGenericProperties() {
		final Map<String,Supplier<?>> m = new LinkedHashMap<>();
		m.put("isHorizontal", this::getHorizontalTextAlignment);
		m.put("isVertical", this::getVerticalTextAlignment);
		m.put("textLocked", this::isTextLocked);
		m.put("textOrientation", this::getTextOrientation);
		m.put("string", this::getStr);
		m.put("reserved4", () -> field_3_reserved4);
		m.put("reserved5", () -> field_4_reserved5);
		m.put("reserved6", () -> field_5_reserved6);
		m.put("reserved7", () -> field_8_reserved7);
		return Collections.unmodifiableMap(m);
	}
}
