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

import java.io.IOException;

import org.apache.poi.hwpf.model.io.HWPFOutputStream;
import org.apache.poi.hwpf.sprm.CharacterSprmUncompressor;
import org.apache.poi.hwpf.sprm.ParagraphSprmUncompressor;
import org.apache.poi.hwpf.usermodel.CharacterProperties;
import org.apache.poi.hwpf.usermodel.ParagraphProperties;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian;

/**
 * Represents a document's stylesheet. A word documents formatting is stored as
 * compressed styles that are based on styles contained in the stylesheet. This
 * class also contains static utility functions to uncompress different
 * formatting properties.
 * <p>
 * Fields documentation is quotes from Microsoft Office Word 97-2007 Binary File
 * Format (.doc) Specification, page 36 of 210
 * 
 * @author Ryan Ackley
 */
@Internal
public final class StyleSheet implements HDFType {

  public static final int NIL_STYLE = 4095;
//  private static final int PAP_TYPE = 1;
//  private static final int CHP_TYPE = 2;
//  private static final int SEP_TYPE = 4;
//  private static final int TAP_TYPE = 5;

    @Deprecated
    private final static ParagraphProperties NIL_PAP = new ParagraphProperties();
    @Deprecated
    private final static CharacterProperties NIL_CHP = new CharacterProperties();

  private final static byte[] NIL_CHPX = new byte[] {};
  private final static byte[] NIL_PAPX = new byte[] {0, 0};

    /**
     * Size of the STSHI structure
     */
    private int _cbStshi;

    /**
     * General information about a stylesheet
     */
    private Stshif _stshif;
    
  StyleDescription[] _styleDescriptions;

  /**
   * StyleSheet constructor. Loads a document's stylesheet information,
   *
   * @param tableStream A byte array containing a document's raw stylesheet
   *        info. Found by using FileInformationBlock.getFcStshf() and
   *        FileInformationBLock.getLcbStshf()
   */
  public StyleSheet(byte[] tableStream, int offset)
  {
        int startOffset = offset;
        _cbStshi = LittleEndian.getShort( tableStream, offset );
        offset += LittleEndian.SHORT_SIZE;

        /*
         * Count of styles in stylesheet
         * 
         * The number of styles in this style sheet. There will be stshi.cstd
         * (cbSTD, STD) pairs in the file following the STSHI. Note: styles can
         * be empty, i.e. cbSTD==0.
         */
        
        _stshif = new Stshif( tableStream, offset );
        offset += Stshif.getSize();

        // shall we discard cbLSD and mpstilsd?
        
      offset = startOffset + LittleEndian.SHORT_SIZE + _cbStshi;
      _styleDescriptions = new StyleDescription[_stshif.getCstd()];
      for(int x = 0; x < _stshif.getCstd(); x++)
      {
          int stdSize = LittleEndian.getShort(tableStream, offset);
          //get past the size
          offset += 2;
          if(stdSize > 0)
          {
              //byte[] std = new byte[stdSize];

              StyleDescription aStyle = new StyleDescription(tableStream,
                      _stshif.getCbSTDBaseInFile(), offset, true);

              _styleDescriptions[x] = aStyle;
          }

          offset += stdSize;

      }
      for(int x = 0; x < _styleDescriptions.length; x++)
      {
          if(_styleDescriptions[x] != null)
          {
              createPap(x);
              createChp(x);
          }
      }
  }

  public void writeTo(HWPFOutputStream out)
    throws IOException
  {

    int offset = 0;

        /*
         * we don't support 2003 Word extensions in STSHI (but may be we should
         * at least not delete them, shouldn't we?), so our structure is always
         * 18 bytes in length -- sergey
         */
        this._cbStshi = 18;

    // add two bytes so we can prepend the stylesheet w/ its size
    byte[] buf = new byte[_cbStshi + 2];

    LittleEndian.putUShort(buf, offset, (short)_cbStshi);
    offset += LittleEndian.SHORT_SIZE;

    _stshif.setCstd( _styleDescriptions.length );
    _stshif.serialize( buf, offset );
    // offset += Stshif.getSize();

    out.write(buf);

    byte[] sizeHolder = new byte[2];
    for (int x = 0; x < _styleDescriptions.length; x++)
    {
      if(_styleDescriptions[x] != null)
      {
          byte[] std = _styleDescriptions[x].toByteArray();

          // adjust the size so it is always on a word boundary
          LittleEndian.putShort(sizeHolder, 0, (short)((std.length) + (std.length % 2)));
          out.write(sizeHolder);
          out.write(std);

          // Must always start on a word boundary.
          if (std.length % 2 == 1)
          {
            out.write('\0');
          }
      }
      else
      {
        sizeHolder[0] = 0;
        sizeHolder[1] = 0;
        out.write(sizeHolder);
      }
    }
  }

  @Override
  public boolean equals(Object o)
  {
    if (!(o instanceof StyleSheet)) return false;
    StyleSheet ss = (StyleSheet)o;

    if (!ss._stshif.equals( this._stshif )
        || ss._cbStshi != this._cbStshi
        || ss._styleDescriptions.length != this._styleDescriptions.length
    ) return false;
    
    for (int i=0; i<_styleDescriptions.length; i++) {
        StyleDescription tsd = this._styleDescriptions[i];
        StyleDescription osd = ss._styleDescriptions[i];
        if (tsd == null && osd == null) continue;
        if (tsd == null || osd == null || !osd.equals(tsd)) return false;
    }

    return true;
  }

  @Override
  public int hashCode() {
      assert false : "hashCode not designed";
      return 42; // any arbitrary constant will do
  }

  /**
   * Creates a PartagraphProperties object from a papx stored in the
   * StyleDescription at the index istd in the StyleDescription array. The PAP
   * is placed in the StyleDescription at istd after its been created. Not
   * every StyleDescription will contain a papx. In these cases this function
   * does nothing
   *
   * @param istd The index of the StyleDescription to create the
   *        ParagraphProperties  from (and also place the finished PAP in)
   */
  @Deprecated
  private void createPap(int istd)
  {
      StyleDescription sd = _styleDescriptions[istd];
      ParagraphProperties pap = sd.getPAP();
      byte[] papx = sd.getPAPX();
      int baseIndex = sd.getBaseStyle();
      if(pap == null && papx != null)
      {
          ParagraphProperties parentPAP = new ParagraphProperties();
          if(baseIndex != NIL_STYLE)
          {

              parentPAP = _styleDescriptions[baseIndex].getPAP();
              if(parentPAP == null) {
                  if(baseIndex == istd) {
                      // Oh dear, style claims that it is its own parent
                      throw new IllegalStateException("Pap style " + istd + " claimed to have itself as its parent, which isn't allowed");
                  }
                  // Create the parent style
                  createPap(baseIndex);
                  parentPAP = _styleDescriptions[baseIndex].getPAP();
              }

          }

          if (parentPAP == null) {
              parentPAP = new ParagraphProperties();
          }

          pap = ParagraphSprmUncompressor.uncompressPAP(parentPAP, papx, 2);
          sd.setPAP(pap);
      }
  }
  /**
   * Creates a CharacterProperties object from a chpx stored in the
   * StyleDescription at the index istd in the StyleDescription array. The
   * CharacterProperties object is placed in the StyleDescription at istd after
   * its been created. Not every StyleDescription will contain a chpx. In these
   * cases this function does nothing.
   *
   * @param istd The index of the StyleDescription to create the
   *        CharacterProperties object from.
   */
  @Deprecated
  private void createChp(int istd)
  {
      StyleDescription sd = _styleDescriptions[istd];
      CharacterProperties chp = sd.getCHP();
      byte[] chpx = sd.getCHPX();
      int baseIndex = sd.getBaseStyle();
      
      if(baseIndex == istd) {
         // Oh dear, this isn't allowed...
         // The word file seems to be corrupted
         // Switch to using the nil style so that
         //  there's a chance we can read it
         baseIndex = NIL_STYLE;
      }
      
      // Build and decompress the Chp if required 
      if(chp == null && chpx != null)
      {
          CharacterProperties parentCHP = new CharacterProperties();
          if(baseIndex != NIL_STYLE)
          {
              parentCHP = _styleDescriptions[baseIndex].getCHP();
              if(parentCHP == null)
              {
                  createChp(baseIndex);
                  parentCHP = _styleDescriptions[baseIndex].getCHP();
              }
              if(parentCHP == null) {
                  parentCHP = new CharacterProperties();
              }
          }

          chp = CharacterSprmUncompressor.uncompressCHP(parentCHP, chpx, 0);
          sd.setCHP(chp);
      }
  }

  /**
   * Gets the number of styles in the style sheet.
   * @return The number of styles in the style sheet.
   */
  public int numStyles() {
      return _styleDescriptions.length;
  }

    /**
     * Gets the StyleDescription at index x.
     * 
     * @param styleIndex
     *            the index of the desired StyleDescription.
     */
    public StyleDescription getStyleDescription( int styleIndex )
    {
        return _styleDescriptions[styleIndex];
    }

    @Deprecated
    public CharacterProperties getCharacterStyle( int styleIndex )
    {
        if ( styleIndex == NIL_STYLE )
        {
            return NIL_CHP;
        }

        if ( styleIndex >= _styleDescriptions.length )
        {
            return NIL_CHP;
        }

        return ( _styleDescriptions[styleIndex] != null ? _styleDescriptions[styleIndex]
                .getCHP() : NIL_CHP );
    }

    @Deprecated
    public ParagraphProperties getParagraphStyle( int styleIndex )
    {
        if ( styleIndex == NIL_STYLE )
        {
            return NIL_PAP;
        }

        if ( styleIndex >= _styleDescriptions.length )
        {
            return NIL_PAP;
        }

        if ( _styleDescriptions[styleIndex] == null )
        {
            return NIL_PAP;
        }

        if ( _styleDescriptions[styleIndex].getPAP() == null )
        {
            return NIL_PAP;
        }

        return _styleDescriptions[styleIndex].getPAP();
    }

    public byte[] getCHPX( int styleIndex )
    {
        if ( styleIndex == NIL_STYLE )
        {
            return NIL_CHPX;
        }

        if ( styleIndex >= _styleDescriptions.length )
        {
            return NIL_CHPX;
        }

        if ( _styleDescriptions[styleIndex] == null )
        {
            return NIL_CHPX;
        }

        if ( _styleDescriptions[styleIndex].getCHPX() == null )
        {
            return NIL_CHPX;
        }

        return _styleDescriptions[styleIndex].getCHPX();
    }

    public byte[] getPAPX( int styleIndex )
    {
        if ( styleIndex == NIL_STYLE )
        {
            return NIL_PAPX;
        }

        if ( styleIndex >= _styleDescriptions.length )
        {
            return NIL_PAPX;
        }

        if ( _styleDescriptions[styleIndex] == null )
        {
            return NIL_PAPX;
        }

        if ( _styleDescriptions[styleIndex].getPAPX() == null )
        {
            return NIL_PAPX;
        }

        return _styleDescriptions[styleIndex].getPAPX();
    }
}
