/* ====================================================================
   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 org.apache.poi.ss.formula.Formula;
import org.apache.poi.ss.formula.constant.ConstantValueParser;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.StringUtil;

/**
 * EXTERNALNAME (0x0023)
 */
public final class ExternalNameRecord extends StandardRecord {

	public final static short sid = 0x0023; // as per BIFF8. (some old versions used 0x223)

	private static final int OPT_BUILTIN_NAME          = 0x0001;
	private static final int OPT_AUTOMATIC_LINK        = 0x0002; // m$ doc calls this fWantAdvise
	private static final int OPT_PICTURE_LINK          = 0x0004;
	private static final int OPT_STD_DOCUMENT_NAME     = 0x0008; //fOle
	private static final int OPT_OLE_LINK              = 0x0010; //fOleLink
//	private static final int OPT_CLIP_FORMAT_MASK      = 0x7FE0;
	private static final int OPT_ICONIFIED_PICTURE_LINK= 0x8000;


	private short  field_1_option_flag;
	private short  field_2_ixals;
	private short  field_3_not_used;
	private String field_4_name;
	private Formula  field_5_name_definition;

	/**
	 * 'rgoper' / 'Last received results of the DDE link'
	 * (seems to be only applicable to DDE links)<br>
	 * Logically this is a 2-D array, which has been flattened into 1-D array here.
	 */
	private Object[] _ddeValues;
	/**
	 * (logical) number of columns in the {@link #_ddeValues} array
	 */
	private int _nColumns;
	/**
	 * (logical) number of rows in the {@link #_ddeValues} array
	 */
	private int _nRows;

	/**
	 * @return {@code true} if the name is a built-in name
	 */
	public boolean isBuiltInName() {
		return (field_1_option_flag & OPT_BUILTIN_NAME) != 0;
	}
	/**
	 * For OLE and DDE, links can be either 'automatic' or 'manual'
	 * 
	 * @return {@code true} if this is a automatic link
	 */
	public boolean isAutomaticLink() {
		return (field_1_option_flag & OPT_AUTOMATIC_LINK) != 0;
	}
	/**
	 * only for OLE and DDE
	 * 
	 * @return {@code true} if this is a picture link
	 */
	public boolean isPicureLink() {
		return (field_1_option_flag & OPT_PICTURE_LINK) != 0;
	}
	/**
	 * DDE links only. If <code>true</code>, this denotes the 'StdDocumentName'
	 * 
	 * @return {@code true} if this denotes the 'StdDocumentName'
	 */
	public boolean isStdDocumentNameIdentifier() {
		return (field_1_option_flag & OPT_STD_DOCUMENT_NAME) != 0;
	}
	public boolean isOLELink() {
		return (field_1_option_flag & OPT_OLE_LINK) != 0;
	}
	public boolean isIconifiedPictureLink() {
		return (field_1_option_flag & OPT_ICONIFIED_PICTURE_LINK) != 0;
	}
	/**
	 * @return the standard String representation of this name
	 */
	public String getText() {
		return field_4_name;
	}
	
    public void setText(String str) {
        field_4_name = str;
    }

	/**
	 * If this is a local name, then this is the (1 based)
	 *  index of the name of the Sheet this refers to, as
	 *  defined in the preceding {@link SupBookRecord}.
	 * If it isn't a local name, then it must be zero.
	 * 
	 * @return the index of the name of the Sheet this refers to
	 */
	public short getIx() {
	   return field_2_ixals;
	}
	
    public void setIx(short ix) {
        field_2_ixals = ix;
    }

    public Ptg[] getParsedExpression() {
        return Formula.getTokens(field_5_name_definition);
    }
    public void setParsedExpression(Ptg[] ptgs) {
        field_5_name_definition = Formula.create(ptgs);
    }


	@Override
	protected int getDataSize(){
		int result = 2 + 4;  // short and int
        result += StringUtil.getEncodedSize(field_4_name) - 1; //size is byte, not short 

        if(!isOLELink() && !isStdDocumentNameIdentifier()){
            if(isAutomaticLink()){
            	if(_ddeValues != null) {
                    result += 3; // byte, short
                    result += ConstantValueParser.getEncodedSize(_ddeValues);
            	}
            } else {
                result += field_5_name_definition.getEncodedSize();
            }
        }
		return result;
	}

	@Override
	public void serialize(LittleEndianOutput out) {
		out.writeShort(field_1_option_flag);
		out.writeShort(field_2_ixals);
		out.writeShort(field_3_not_used);

		out.writeByte(field_4_name.length());
		StringUtil.writeUnicodeStringFlagAndData(out, field_4_name);

        if(!isOLELink() && !isStdDocumentNameIdentifier()){
            if(isAutomaticLink()){
            	if(_ddeValues != null) {
                    out.writeByte(_nColumns-1);
                    out.writeShort(_nRows-1);
                    ConstantValueParser.encode(out, _ddeValues);
            	}
            } else {
                field_5_name_definition.serialize(out);
            }
        }
	}

    public ExternalNameRecord() {
        field_2_ixals = 0;
    }
    
    public ExternalNameRecord(RecordInputStream in) {
		field_1_option_flag = in.readShort();
		field_2_ixals       = in.readShort();
      field_3_not_used    = in.readShort();

        int numChars = in.readUByte();
        field_4_name = StringUtil.readUnicodeString(in, numChars);

        // the record body can take different forms.
        // The form is dictated by the values of 3-th and 4-th bits in field_1_option_flag
        if(!isOLELink() && !isStdDocumentNameIdentifier()){
            // another switch: the fWantAdvise bit specifies whether the body describes
            // an external defined name or a DDE data item
            if(isAutomaticLink()){
                if(in.available() > 0) {
                   //body specifies DDE data item
                   int nColumns = in.readUByte() + 1;
                   int nRows = in.readShort() + 1;
   
                   int totalCount = nRows * nColumns;
                   _ddeValues = ConstantValueParser.parse(in, totalCount);
                   _nColumns = nColumns;
                   _nRows = nRows;
                }
            } else {
                //body specifies an external defined name
                int formulaLen = in.readUShort();
                field_5_name_definition = Formula.read(formulaLen, in);
            }
        }
    }

	@Override
	public short getSid() {
		return sid;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("[EXTERNALNAME]\n");
        sb.append("    .options = ").append(field_1_option_flag).append("\n");
		sb.append("    .ix      = ").append(field_2_ixals).append("\n");
		sb.append("    .name    = ").append(field_4_name).append("\n");
		if(field_5_name_definition != null) {
            Ptg[] ptgs = field_5_name_definition.getTokens();
            for (Ptg ptg : ptgs) {
                sb.append("    .namedef = ").append(ptg).append(ptg.getRVAType()).append("\n");
            }
		}
		sb.append("[/EXTERNALNAME]\n");
		return sb.toString();
	}
}
