/* ====================================================================
   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() {
		StringBuffer sb = new StringBuffer();
		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(ptg.toString()).append(ptg.getRVAType()).append("\n");
            }
		}
		sb.append("[/EXTERNALNAME]\n");
		return sb.toString();
	}
}
