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

import org.apache.poi.ddf.*;
import org.apache.poi.hslf.model.ShapeTypes;
import org.apache.poi.hslf.record.ColorSchemeAtom;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.POILogFactory;

import java.util.Iterator;
import java.awt.*;

/**
 *  <p>
  * Represents a Shape which is the elemental object that composes a drawing.
 *  This class is a wrapper around EscherSpContainer which holds all information
 *  about a shape in PowerPoint document.
 *  </p>
 *  <p>
 *  When you add a shape, you usually specify the dimensions of the shape and the position
 *  of the upper�left corner of the bounding box for the shape relative to the upper�left
 *  corner of the page, worksheet, or slide. Distances in the drawing layer are measured
 *  in points (72 points = 1 inch).
 *  </p>
 * <p>
  *
  * @author Yegor Kozlov
 */
public abstract class Shape {

    // For logging
    protected POILogger logger = POILogFactory.getLogger(this.getClass());

    /**
     * In Escher absolute distances are specified in
     * English Metric Units (EMUs), occasionally referred to as A units;
     * there are 360000 EMUs per centimeter, 914400 EMUs per inch, 12700 EMUs per point.
     */
    public static final int EMU_PER_INCH = 914400;
    public static final int EMU_PER_POINT = 12700;
    public static final int EMU_PER_CENTIMETER = 360000;

    /**
     * Master DPI (576 pixels per inch).
     * Used by the reference coordinate system in PowerPoint.
     */
    public static final int MASTER_DPI = 576;

    /**
     * Pixels DPI (96 pixels per inch)
     */
    public static final int PIXEL_DPI = 96;

    /**
     * Points DPI (72 pixels per inch)
     */
    public static final int POINT_DPI = 72;

    /**
     * Either EscherSpContainer or EscheSpgrContainer record
     * which holds information about this shape.
     */
    protected EscherContainerRecord _escherContainer;

    /**
     * Parent of this shape.
     * <code>null</code> for the topmost shapes.
     */
    protected Shape _parent;

    /**
     * The <code>Sheet</code> this shape belongs to
     */
    protected Sheet _sheet;

    /**
     * Create a Shape object. This constructor is used when an existing Shape is read from from a PowerPoint document.
     *
     * @param escherRecord       <code>EscherSpContainer</code> container which holds information about this shape
     * @param parent             the parent of this Shape
     */
      protected Shape(EscherContainerRecord escherRecord, Shape parent){
        _escherContainer = escherRecord;
        _parent = parent;
     }

    /**
     * Creates the lowerlevel escher records for this shape.
     */
    protected abstract EscherContainerRecord createSpContainer(boolean isChild);

    /**
     *  @return the parent of this shape
     */
    public Shape getParent(){
        return _parent;
    }

    /**
     * @return name of the shape.
     */
    public String getShapeName(){
        return ShapeTypes.typeName(getShapeType());
    }

    /**
     * @return type of the shape.
     * @see org.apache.poi.hslf.record.RecordTypes
     */
    public int getShapeType(){
        EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
        return spRecord.getOptions() >> 4;
    }

    /**
     * @param type type of the shape.
     * @see org.apache.poi.hslf.record.RecordTypes
     */
    public void setShapeType(int type){
        EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
        spRecord.setOptions((short)(type << 4 | 0x2));
    }

    /**
     * Returns the anchor (the bounding box rectangle) of this shape.
     * All coordinates are expressed in points (72 dpi).
     *
     * @return the anchor of this shape
     */
    public java.awt.Rectangle getAnchor(){
        EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
        int flags = spRecord.getFlags();
        java.awt.Rectangle anchor=null;
        if ((flags & EscherSpRecord.FLAG_CHILD) != 0){
            EscherChildAnchorRecord rec = (EscherChildAnchorRecord)getEscherChild(_escherContainer, EscherChildAnchorRecord.RECORD_ID);
            anchor = new java.awt.Rectangle();
            anchor.x = rec.getDx1()*POINT_DPI/MASTER_DPI;
            anchor.y = rec.getDy1()*POINT_DPI/MASTER_DPI;
            anchor.width = rec.getDx2()*POINT_DPI/MASTER_DPI - anchor.x;
            anchor.height = rec.getDy2()*POINT_DPI/MASTER_DPI - anchor.y;
        }
        else {
            EscherClientAnchorRecord rec = (EscherClientAnchorRecord)getEscherChild(_escherContainer, EscherClientAnchorRecord.RECORD_ID);
            anchor = new java.awt.Rectangle();
            anchor.y = rec.getFlag()*POINT_DPI/MASTER_DPI;
            anchor.x = rec.getCol1()*POINT_DPI/MASTER_DPI;
            anchor.width = (rec.getDx1() - rec.getCol1())*POINT_DPI/MASTER_DPI;
            anchor.height = (rec.getRow1() - rec.getFlag())*POINT_DPI/MASTER_DPI;
        }
        return anchor;
    }

    /**
     * Sets the anchor (the bounding box rectangle) of this shape.
     * All coordinates should be expressed in points (72 dpi).
     *
     * @param anchor new anchor
     */
    public void setAnchor(java.awt.Rectangle anchor){
        EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
        int flags = spRecord.getFlags();
        if ((flags & EscherSpRecord.FLAG_CHILD) != 0){
            EscherChildAnchorRecord rec = (EscherChildAnchorRecord)getEscherChild(_escherContainer, EscherChildAnchorRecord.RECORD_ID);
            rec.setDx1(anchor.x*MASTER_DPI/POINT_DPI);
            rec.setDy1(anchor.y*MASTER_DPI/POINT_DPI);
            rec.setDx2((anchor.width + anchor.x)*MASTER_DPI/POINT_DPI);
            rec.setDy2((anchor.height + anchor.y)*MASTER_DPI/POINT_DPI);
        }
        else {
            EscherClientAnchorRecord rec = (EscherClientAnchorRecord)getEscherChild(_escherContainer, EscherClientAnchorRecord.RECORD_ID);
            rec.setFlag((short)(anchor.y*MASTER_DPI/POINT_DPI));
            rec.setCol1((short)(anchor.x*MASTER_DPI/POINT_DPI));
            rec.setDx1((short)((anchor.width + anchor.x)*MASTER_DPI/POINT_DPI));
            rec.setRow1((short)((anchor.height + anchor.y)*MASTER_DPI/POINT_DPI));
        }

    }

    /**
     * Moves the top left corner of the shape to the specified point.
     *
     * @param x the x coordinate of the top left corner of the shape
     * @param y the y coordinate of the top left corner of the shape
     */
    public void moveTo(int x, int y){
        java.awt.Rectangle anchor = getAnchor();
        anchor.setLocation(x, y);
        setAnchor(anchor);
    }

    /**
     * Helper method to return escher child by record ID
     *
     * @return escher record or <code>null</code> if not found.
     */
    public static EscherRecord getEscherChild(EscherContainerRecord owner, int recordId){
        for ( Iterator iterator = owner.getChildRecords().iterator(); iterator.hasNext(); )
        {
            EscherRecord escherRecord = (EscherRecord) iterator.next();
            if (escherRecord.getRecordId() == recordId)
                return escherRecord;
        }
        return null;
    }

    /**
     * Returns  escher property by id.
     *
     * @return escher property or <code>null</code> if not found.
     */
     public static EscherProperty getEscherProperty(EscherOptRecord opt, int propId){
        for ( Iterator iterator = opt.getEscherProperties().iterator(); iterator.hasNext(); )
        {
            EscherProperty prop = (EscherProperty) iterator.next();
            if (prop.getPropertyNumber() == propId)
                return prop;
        }
        return null;
    }

    /**
     * Set an escher property for this shape.
     *
     * @param opt       The opt record to set the properties to.
     * @param propId    The id of the property. One of the constants defined in EscherOptRecord.
     * @param value     value of the property. If value = -1 then the property is removed.
     */
     public static void setEscherProperty(EscherOptRecord opt, short propId, int value){
        java.util.List props = opt.getEscherProperties();
        for ( Iterator iterator = props.iterator(); iterator.hasNext(); ) {
            EscherProperty prop = (EscherProperty) iterator.next();
            if (prop.getId() == propId){
                iterator.remove();
            }
        }
        if (value != -1) {
            opt.addEscherProperty(new EscherSimpleProperty(propId, value));
            opt.sortProperties();
        }
    }

    /**
     * @return  The shape container and it's children that can represent this
     *          shape.
     */
    public EscherContainerRecord getSpContainer(){
        return _escherContainer;
    }

    /**
     * Event which fires when a shape is inserted in the sheet.
     * In some cases we need to propagate changes to upper level containers.
     * <br>
     * Default implementation does nothing.
     *
     * @param sh - owning shape
     */
    protected void afterInsert(Sheet sh){

    }

    /**
     *  @return the <code>SlideShow</code> this shape belongs to
     */
    public Sheet getSheet(){
        return _sheet;
    }

    /**
     * Assign the <code>SlideShow</code> this shape belongs to
     *
     * @param sheet owner of this shape
     */
    public void setSheet(Sheet sheet){
        _sheet = sheet;
    }

    protected Color getColor(int rgb){
        if (rgb >= 0x8000000) {
            int idx = rgb - 0x8000000;
            ColorSchemeAtom ca = getSheet().getColorScheme();
            if(idx >= 0 && idx <= 7) rgb = ca.getColor(idx);
        }
        Color tmp = new Color(rgb, true);
        return new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed());
    }

    /**
     * Fill properties of this shape
     *
     * @return fill properties of this shape
     */
    public Fill getFill(){
        return new Fill(this);
    }


    /**
     * Returns the hyperlink assigned to this shape
     *
     * @return the hyperlink assigned to this shape
     * or <code>null</code> if not found.
     */
     public Hyperlink getHyperlink(){
        return Hyperlink.find(this);
    }

}
