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

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherChildAnchorRecord;
import org.apache.poi.ddf.EscherClientAnchorRecord;
import org.apache.poi.ddf.EscherColorRef;
import org.apache.poi.ddf.EscherColorRef.SysIndexProcedure;
import org.apache.poi.ddf.EscherColorRef.SysIndexSource;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.ddf.EscherProperty;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.hslf.record.ColorSchemeAtom;
import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.usermodel.FillStyle;
import org.apache.poi.sl.usermodel.PresetColor;
import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.Units;

/**
 *  <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>
 */
public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {

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

    /**
     * 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 ShapeContainer<HSLFShape,HSLFTextParagraph> _parent;

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

    /**
     * Fill
     */
    protected HSLFFill _fill;
    
    /**
     * 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 HSLFShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape,HSLFTextParagraph> 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 ShapeContainer<HSLFShape,HSLFTextParagraph> getParent(){
        return _parent;
    }

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

    public ShapeType getShapeType(){
        EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
        return ShapeType.forId(spRecord.getShapeType(), false);
    }

    public void setShapeType(ShapeType type){
        EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
        spRecord.setShapeType( (short) type.nativeId );
        spRecord.setVersion( (short) 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 Rectangle2D getAnchor() {
        EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
        int flags = spRecord.getFlags();
        int x1,y1,x2,y2;
        EscherChildAnchorRecord childRec = getEscherChild(EscherChildAnchorRecord.RECORD_ID);
        boolean useChildRec = ((flags & EscherSpRecord.FLAG_CHILD) != 0);
        if (useChildRec && childRec != null){
            x1 = childRec.getDx1();
            y1 = childRec.getDy1();
            x2 = childRec.getDx2();
            y2 = childRec.getDy2();
        } else {
            if (useChildRec) {
                logger.log(POILogger.WARN, "EscherSpRecord.FLAG_CHILD is set but EscherChildAnchorRecord was not found");
            }
            EscherClientAnchorRecord clientRec = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
            x1 = clientRec.getCol1();
            y1 = clientRec.getFlag();
            x2 = clientRec.getDx1();
            y2 = clientRec.getRow1();
        }

        // TODO: find out where this -1 value comes from at #57820 (link to ms docs?)
        Rectangle2D anchor = new Rectangle2D.Double(
            (x1 == -1 ? -1 : Units.masterToPoints(x1)),
            (y1 == -1 ? -1 : Units.masterToPoints(y1)),
            (x2 == -1 ? -1 : Units.masterToPoints(x2-x1)),
            (y2 == -1 ? -1 : Units.masterToPoints(y2-y1))
        );
        
        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(Rectangle2D anchor){
        int x = Units.pointsToMaster(anchor.getX());
        int y = Units.pointsToMaster(anchor.getY());
        int w = Units.pointsToMaster(anchor.getWidth() + anchor.getX());
        int h = Units.pointsToMaster(anchor.getHeight() + anchor.getY());
        EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
        int flags = spRecord.getFlags();
        if ((flags & EscherSpRecord.FLAG_CHILD) != 0){
            EscherChildAnchorRecord rec = (EscherChildAnchorRecord)getEscherChild(EscherChildAnchorRecord.RECORD_ID);
            rec.setDx1(x);
            rec.setDy1(y);
            rec.setDx2(w);
            rec.setDy2(h);
        } else {
            EscherClientAnchorRecord rec = (EscherClientAnchorRecord)getEscherChild(EscherClientAnchorRecord.RECORD_ID);
            rec.setCol1((short)x);
            rec.setFlag((short)y);
            rec.setDx1((short)w);
            rec.setRow1((short)h);
        }

    }

    /**
     * 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 final void moveTo(double x, double y) {
        // This convenience method should be implemented via setAnchor in subclasses
        // see HSLFGroupShape.setAnchor() for a reference
        Rectangle2D anchor = getAnchor();
        anchor.setRect(x, y, anchor.getWidth(), anchor.getHeight());
        setAnchor(anchor);
    }

    /**
     * Helper method to return escher child by record ID
     *
     * @return escher record or <code>null</code> if not found.
     */
    public static <T extends EscherRecord> T getEscherChild(EscherContainerRecord owner, int recordId){
        return owner.getChildById((short)recordId);
    }
    
    /**
     * @since POI 3.14-Beta2
     */
    public static <T extends EscherRecord> T getEscherChild(EscherContainerRecord owner, RecordTypes recordId){
        return getEscherChild(owner, recordId.typeID);
    }

    public <T extends EscherRecord> T getEscherChild(int recordId){
        return _escherContainer.getChildById((short)recordId);
    }
    
    /**
     * @since POI 3.14-Beta2
     */
    public <T extends EscherRecord> T getEscherChild(RecordTypes recordId){
        return getEscherChild(recordId.typeID);
    }
    
    /**
     * Returns  escher property by id.
     *
     * @return escher property or <code>null</code> if not found.
     */
     public static <T extends EscherProperty> T getEscherProperty(AbstractEscherOptRecord opt, int propId){
         return (opt == null) ? null : opt.<T>lookup(propId);
     }

    /**
     * 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(AbstractEscherOptRecord opt, short propId, int value){
        java.util.List<EscherProperty> props = opt.getEscherProperties();
        for ( Iterator<EscherProperty> iterator = props.iterator(); iterator.hasNext(); ) {
            if (iterator.next().getPropertyNumber() == propId){
                iterator.remove();
                break;
            }
        }
        if (value != -1) {
            opt.addEscherProperty(new EscherSimpleProperty(propId, value));
            opt.sortProperties();
        }
    }

    /**
     * Set an simple escher property for this shape.
     *
     * @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 void setEscherProperty(short propId, int value){
        AbstractEscherOptRecord opt = getEscherOptRecord();
        setEscherProperty(opt, propId, value);
    }

    /**
     * Get the value of a simple escher property for this shape.
     *
     * @param propId    The id of the property. One of the constants defined in EscherOptRecord.
     */
   public int getEscherProperty(short propId){
       AbstractEscherOptRecord opt = getEscherOptRecord();
        EscherSimpleProperty prop = getEscherProperty(opt, propId);
        return prop == null ? 0 : prop.getPropertyValue();
    }

    /**
     * Get the value of a simple escher property for this shape.
     *
     * @param propId    The id of the property. One of the constants defined in EscherOptRecord.
     */
   public int getEscherProperty(short propId, int defaultValue){
       AbstractEscherOptRecord opt = getEscherOptRecord();
        EscherSimpleProperty prop = getEscherProperty(opt, propId);
        return prop == null ? defaultValue : prop.getPropertyValue();
    }

    /**
     * @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(HSLFSheet sh){
        if(_fill != null) {
            _fill.afterInsert(sh);
        }
    }

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

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

    Color getColor(short colorProperty, short opacityProperty, int defaultColor){
        AbstractEscherOptRecord opt = getEscherOptRecord();
        EscherSimpleProperty p = getEscherProperty(opt, colorProperty);
        if(p == null && defaultColor == -1) return null;

        int val = (p == null) ? defaultColor : p.getPropertyValue();

        EscherColorRef ecr = new EscherColorRef(val);
        Color col = getColor(ecr);
        if (col == null) {
            return null;
        }

        double alpha = getAlpha(opacityProperty);
        return new Color(col.getRed(), col.getGreen(), col.getBlue(), (int)(alpha*255.0));
    }

    Color getColor(EscherColorRef ecr) {
        boolean fPaletteIndex = ecr.hasPaletteIndexFlag();
        boolean fPaletteRGB = ecr.hasPaletteRGBFlag();
        boolean fSystemRGB = ecr.hasSystemRGBFlag();
        boolean fSchemeIndex = ecr.hasSchemeIndexFlag();
        boolean fSysIndex = ecr.hasSysIndexFlag();
        
        int rgb[] = ecr.getRGB();

        HSLFSheet sheet = getSheet();
        if (fSchemeIndex && sheet != null) {
            //red is the index to the color scheme
            ColorSchemeAtom ca = sheet.getColorScheme();
            int schemeColor = ca.getColor(ecr.getSchemeIndex());

            rgb[0] = (schemeColor >> 0) & 0xFF;
            rgb[1] = (schemeColor >> 8) & 0xFF;
            rgb[2] = (schemeColor >> 16) & 0xFF;
        } else if (fPaletteIndex) {
            //TODO
        } else if (fPaletteRGB) {
            //TODO
        } else if (fSystemRGB) {
            //TODO
        } else if (fSysIndex) {
            Color col = getSysIndexColor(ecr);
            col = applySysIndexProcedure(ecr, col);
            return col;
        }
        
        return new Color(rgb[0], rgb[1], rgb[2]);
    }
    
    private Color getSysIndexColor(EscherColorRef ecr) {
        SysIndexSource sis = ecr.getSysIndexSource();
        if (sis == null) {
            int sysIdx = ecr.getSysIndex();
            PresetColor pc = PresetColor.valueOfNativeId(sysIdx);
            return (pc != null) ? pc.color : null;
        }
        
        // TODO: check for recursive loops, when color getter also reference
        // a different color type
        switch (sis) {
            case FILL_COLOR: {
                return getFill().getForegroundColor();
            }
            case LINE_OR_FILL_COLOR: {
                Color col = null;
                if (this instanceof HSLFSimpleShape) {
                    col = ((HSLFSimpleShape)this).getLineColor();
                }
                if (col == null) {
                    col = getFill().getForegroundColor();
                }
                return col;
            }
            case LINE_COLOR: {
                if (this instanceof HSLFSimpleShape) {
                    return ((HSLFSimpleShape)this).getLineColor();
                }
                break;
            }
            case SHADOW_COLOR: {
                if (this instanceof HSLFSimpleShape) {
                    return ((HSLFSimpleShape)this).getShadowColor();
                }
                break;
            }
            case CURRENT_OR_LAST_COLOR: {
                // TODO ... read from graphics context???
                break;
            }
            case FILL_BACKGROUND_COLOR: {
                return getFill().getBackgroundColor();
            }
            case LINE_BACKGROUND_COLOR: {
                if (this instanceof HSLFSimpleShape) {
                    return ((HSLFSimpleShape)this).getLineBackgroundColor();
                }
                break;
            }
            case FILL_OR_LINE_COLOR: {
                Color col = getFill().getForegroundColor();
                if (col == null && this instanceof HSLFSimpleShape) {
                    col = ((HSLFSimpleShape)this).getLineColor();
                }
                return col;
            }
            default:
                break;
        }
            
        return null;
    }
        
    private Color applySysIndexProcedure(EscherColorRef ecr, Color col) {
        
        final SysIndexProcedure sip = ecr.getSysIndexProcedure();
        if (col == null || sip == null) {
            return col;
        }
        
        switch (sip) {
            case DARKEN_COLOR: {
                // see java.awt.Color#darken()
                double FACTOR = (ecr.getRGB()[2])/255.;
                int r = (int)Math.rint(col.getRed()*FACTOR);
                int g = (int)Math.rint(col.getGreen()*FACTOR);
                int b = (int)Math.rint(col.getBlue()*FACTOR);
                return new Color(r,g,b);                
            }
            case LIGHTEN_COLOR: {
                double FACTOR = (0xFF-ecr.getRGB()[2])/255.;
                               
                int r = col.getRed();
                int g = col.getGreen();
                int b = col.getBlue();
                
                r += Math.rint((0xFF-r)*FACTOR);
                g += Math.rint((0xFF-g)*FACTOR);
                b += Math.rint((0xFF-b)*FACTOR);
                
                return new Color(r,g,b);
            }
            default:
                // TODO ...
                break;
        }
        
        return col;
    }
    
    double getAlpha(short opacityProperty) {
        AbstractEscherOptRecord opt = getEscherOptRecord();
        EscherSimpleProperty op = getEscherProperty(opt, opacityProperty);
        int defaultOpacity = 0x00010000;
        int opacity = (op == null) ? defaultOpacity : op.getPropertyValue();
        return Units.fixedPointToDouble(opacity);
    }
    
    Color toRGB(int val){
        int a = (val >> 24) & 0xFF;
        int b = (val >> 16) & 0xFF;
        int g = (val >> 8) & 0xFF;
        int r = (val >> 0) & 0xFF;

        if(a == 0xFE){
            // Color is an sRGB value specified by red, green, and blue fields.
        } else if (a == 0xFF){
            // Color is undefined.
        } else {
            // index in the color scheme
            ColorSchemeAtom ca = getSheet().getColorScheme();
            int schemeColor = ca.getColor(a);

            r = (schemeColor >> 0) & 0xFF;
            g = (schemeColor >> 8) & 0xFF;
            b = (schemeColor >> 16) & 0xFF;
        }
        return new Color(r, g, b);
    }

    /**
     * @return id for the shape.
     */
    public int getShapeId(){
        EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
        return spRecord == null ? 0 : spRecord.getShapeId();
    }

    /**
     * Sets shape ID
     *
     * @param id of the shape
     */
    public void setShapeId(int id){
        EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
        if(spRecord != null) spRecord.setShapeId(id);
    }

    /**
     * Fill properties of this shape
     *
     * @return fill properties of this shape
     */
    public HSLFFill getFill(){
        if(_fill == null) {
            _fill = new HSLFFill(this);
        }
        return _fill;
    }

    public FillStyle getFillStyle() {
        return getFill().getFillStyle();
    }

    @Override
    public void draw(Graphics2D graphics, Rectangle2D bounds){
        DrawFactory.getInstance(graphics).drawShape(graphics, this, bounds);
    }

    public AbstractEscherOptRecord getEscherOptRecord() {
        AbstractEscherOptRecord opt = getEscherChild(RecordTypes.EscherOPT);
        if (opt == null) {
            opt = getEscherChild(RecordTypes.EscherUserDefined);
        }
        return opt;
    }
    
    public boolean getFlipHorizontal(){
        EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
        return (spRecord.getFlags()& EscherSpRecord.FLAG_FLIPHORIZ) != 0;
    }
     
    public void setFlipHorizontal(boolean flip) {
        EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
        int flag = spRecord.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ;
        spRecord.setFlags(flag);
    }

    public boolean getFlipVertical(){
        EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
        return (spRecord.getFlags()& EscherSpRecord.FLAG_FLIPVERT) != 0;
    }
    
    public void setFlipVertical(boolean flip) {
        EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
        int flag = spRecord.getFlags() | EscherSpRecord.FLAG_FLIPVERT;
        spRecord.setFlags(flag);
    }

    public double getRotation(){
        int rot = getEscherProperty(EscherProperties.TRANSFORM__ROTATION);
        return Units.fixedPointToDouble(rot);
    }
    
    public void setRotation(double theta){
        int rot = Units.doubleToFixedPoint(theta % 360.0);
        setEscherProperty(EscherProperties.TRANSFORM__ROTATION, rot);
    }

    public boolean isPlaceholder() {
        return false;
    }

    /**
     *  Find a record in the underlying EscherClientDataRecord
     *
     * @param recordType type of the record to search
     */
    @SuppressWarnings("unchecked")
    public <T extends Record> T getClientDataRecord(int recordType) {

        List<? extends Record> records = getClientRecords();
        if (records != null) for (Record r : records) {
            if (r.getRecordType() == recordType){
                return (T)r;
            }
        }
        return null;
    }

    /**
     * Search for EscherClientDataRecord, if found, convert its contents into an array of HSLF records
     *
     * @return an array of HSLF records contained in the shape's EscherClientDataRecord or <code>null</code>
     */
    protected List<? extends Record> getClientRecords() {
        HSLFEscherClientDataRecord clientData = getClientData(false);
        return (clientData == null) ? null : clientData.getHSLFChildRecords();
    }

    /**
     * Create a new HSLF-specific EscherClientDataRecord
     *
     * @param create if true, create the missing record 
     * @return the client record or null if it was missing and create wasn't activated
     */
    protected HSLFEscherClientDataRecord getClientData(boolean create) {
        HSLFEscherClientDataRecord clientData = getEscherChild(HSLFEscherClientDataRecord.RECORD_ID);
        if (clientData == null && create) {
            clientData = new HSLFEscherClientDataRecord();
            clientData.setOptions((short)15);
            clientData.setRecordId(HSLFEscherClientDataRecord.RECORD_ID);
            getSpContainer().addChildBefore(clientData, EscherTextboxRecord.RECORD_ID);
        }
        return clientData;
    }
}
