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

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.ddf.DefaultEscherRecordFactory;
import org.apache.poi.ddf.EscherBoolProperty;
import org.apache.poi.ddf.EscherChildAnchorRecord;
import org.apache.poi.ddf.EscherClientAnchorRecord;
import org.apache.poi.ddf.EscherClientDataRecord;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherOptRecord;
import org.apache.poi.ddf.EscherPropertyTypes;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherRecordTypes;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.ddf.EscherSpgrRecord;
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.EndSubRecord;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.GroupMarkerSubRecord;
import org.apache.poi.hssf.record.ObjRecord;

/**
 * A shape group may contain other shapes.  It was no actual form on the
 * sheet.
 */
public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer {
    private final List<HSSFShape> shapes = new ArrayList<>();
    private EscherSpgrRecord _spgrRecord;

    public HSSFShapeGroup(EscherContainerRecord spgrContainer, ObjRecord objRecord) {
        super(spgrContainer, objRecord);

        // read internal and external coordinates from spgrContainer
        EscherContainerRecord spContainer = spgrContainer.getChildContainers().get(0);
        _spgrRecord = (EscherSpgrRecord) spContainer.getChild(0);
        for (EscherRecord ch : spContainer) {
            switch (EscherRecordTypes.forTypeID(ch.getRecordId())) {
                case SPGR:
                    break;
                case CLIENT_ANCHOR:
                    anchor = new HSSFClientAnchor((EscherClientAnchorRecord) ch);
                    break;
                case CHILD_ANCHOR:
                    anchor = new HSSFChildAnchor((EscherChildAnchorRecord) ch);
                    break;
                default:
                    break;
            }
        }
    }

    public HSSFShapeGroup(HSSFShape parent, HSSFAnchor anchor) {
        super(parent, anchor);
        _spgrRecord = ((EscherContainerRecord)getEscherContainer().getChild(0)).getChildById(EscherSpgrRecord.RECORD_ID);
    }

    @Override
    protected EscherContainerRecord createSpContainer() {
        EscherContainerRecord spgrContainer = new EscherContainerRecord();
        EscherContainerRecord spContainer = new EscherContainerRecord();
        EscherSpgrRecord spgr = new EscherSpgrRecord();
        EscherSpRecord sp = new EscherSpRecord();
        EscherOptRecord opt = new EscherOptRecord();
        EscherRecord anchor;
        EscherClientDataRecord clientData = new EscherClientDataRecord();

        spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER);
        spgrContainer.setOptions((short) 0x000F);
        spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER);
        spContainer.setOptions((short) 0x000F);
        spgr.setRecordId(EscherSpgrRecord.RECORD_ID);
        spgr.setOptions((short) 0x0001);
        spgr.setRectX1(0);
        spgr.setRectY1(0);
        spgr.setRectX2(1023);
        spgr.setRectY2(255);
        sp.setRecordId(EscherSpRecord.RECORD_ID);
        sp.setOptions((short) 0x0002);
        if (getAnchor() instanceof HSSFClientAnchor) {
            sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR);
        } else {
            sp.setFlags(EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD);
        }
        opt.setRecordId(EscherOptRecord.RECORD_ID);
        opt.setOptions((short) 0x0023);
        opt.addEscherProperty(new EscherBoolProperty(EscherPropertyTypes.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004));
        opt.addEscherProperty(new EscherBoolProperty(EscherPropertyTypes.GROUPSHAPE__FLAGS, 0x00080000));

        anchor = getAnchor().getEscherAnchor();
        clientData.setRecordId(EscherClientDataRecord.RECORD_ID);
        clientData.setOptions((short) 0x0000);

        spgrContainer.addChildRecord(spContainer);
        spContainer.addChildRecord(spgr);
        spContainer.addChildRecord(sp);
        spContainer.addChildRecord(opt);
        spContainer.addChildRecord(anchor);
        spContainer.addChildRecord(clientData);
        return spgrContainer;
    }

    @Override
    protected ObjRecord createObjRecord() {
        ObjRecord obj = new ObjRecord();
        CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord();
        cmo.setObjectType(CommonObjectDataSubRecord.OBJECT_TYPE_GROUP);
        cmo.setLocked(true);
        cmo.setPrintable(true);
        cmo.setAutofill(true);
        cmo.setAutoline(true);
        GroupMarkerSubRecord gmo = new GroupMarkerSubRecord();
        EndSubRecord end = new EndSubRecord();
        obj.addSubRecord(cmo);
        obj.addSubRecord(gmo);
        obj.addSubRecord(end);
        return obj;
    }

    @Override
    protected void afterRemove(HSSFPatriarch patriarch) {
        patriarch.getBoundAggregate().removeShapeToObjRecord(getEscherContainer().getChildContainers().get(0)
                .getChildById(EscherClientDataRecord.RECORD_ID));
        for ( int i=0; i<shapes.size(); i++ ) {
            HSSFShape shape = shapes.get(i);
            removeShape(shape);
            shape.afterRemove(getPatriarch());
        }
        shapes.clear();
    }

    private void onCreate(HSSFShape shape){
        if(getPatriarch() != null){
            EscherContainerRecord spContainer = shape.getEscherContainer();
            int shapeId = getPatriarch().newShapeId();
            shape.setShapeId(shapeId);
            getEscherContainer().addChildRecord(spContainer);
            shape.afterInsert(getPatriarch());
            EscherSpRecord sp;
            if (shape instanceof HSSFShapeGroup){
                sp = shape.getEscherContainer().getChildContainers().get(0).getChildById(EscherSpRecord.RECORD_ID);
            } else {
                sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
            }
            sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_CHILD);
        }
    }

    /**
     * Create another group under this group.
     *
     * @param anchor the position of the new group.
     * @return the group
     */
    public HSSFShapeGroup createGroup(HSSFChildAnchor anchor) {
        HSSFShapeGroup group = new HSSFShapeGroup(this, anchor);
        group.setParent(this);
        group.setAnchor(anchor);
        shapes.add(group);
        onCreate(group);
        return group;
    }

    public void addShape(HSSFShape shape) {
        shape.setPatriarch(this.getPatriarch());
        shape.setParent(this);
        shapes.add(shape);
    }

    /**
     * Create a new simple shape under this group.
     *
     * @param anchor the position of the shape.
     * @return the shape
     */
    public HSSFSimpleShape createShape(HSSFChildAnchor anchor) {
        HSSFSimpleShape shape = new HSSFSimpleShape(this, anchor);
        shape.setParent(this);
        shape.setAnchor(anchor);
        shapes.add(shape);
        onCreate(shape);
        EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
        if (shape.getAnchor().isHorizontallyFlipped()){
            sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
        }
        if (shape.getAnchor().isVerticallyFlipped()){
            sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
        }
        return shape;
    }

    /**
     * Create a new textbox under this group.
     *
     * @param anchor the position of the shape.
     * @return the textbox
     */
    public HSSFTextbox createTextbox(HSSFChildAnchor anchor) {
        HSSFTextbox shape = new HSSFTextbox(this, anchor);
        shape.setParent(this);
        shape.setAnchor(anchor);
        shapes.add(shape);
        onCreate(shape);
        return shape;
    }

    /**
     * Creates a polygon
     *
     * @param anchor the client anchor describes how this group is attached
     *               to the sheet.
     * @return the newly created shape.
     */
    public HSSFPolygon createPolygon(HSSFChildAnchor anchor) {
        HSSFPolygon shape = new HSSFPolygon(this, anchor);
        shape.setParent(this);
        shape.setAnchor(anchor);
        shapes.add(shape);
        onCreate(shape);
        return shape;
    }

    /**
     * Creates a picture.
     *
     * @param anchor the client anchor describes how this group is attached
     *               to the sheet.
     * @return the newly created shape.
     */
    public HSSFPicture createPicture(HSSFChildAnchor anchor, int pictureIndex) {
        HSSFPicture shape = new HSSFPicture(this, anchor);
        shape.setParent(this);
        shape.setAnchor(anchor);
        shape.setPictureIndex(pictureIndex);
        shapes.add(shape);
        onCreate(shape);
        EscherSpRecord sp = shape.getEscherContainer().getChildById(EscherSpRecord.RECORD_ID);
        if (shape.getAnchor().isHorizontallyFlipped()){
            sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
        }
        if (shape.getAnchor().isVerticallyFlipped()){
            sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
        }
        return shape;
    }

    /**
     * Return all children contained by this shape.
     */
    public List<HSSFShape> getChildren() {
        return Collections.unmodifiableList(shapes);
    }

    /**
     * Sets the coordinate space of this group.  All children are constrained
     * to these coordinates.
     */
    public void setCoordinates(int x1, int y1, int x2, int y2) {
        _spgrRecord.setRectX1(x1);
        _spgrRecord.setRectX2(x2);
        _spgrRecord.setRectY1(y1);
        _spgrRecord.setRectY2(y2);
    }

    public void clear() {
        ArrayList <HSSFShape> copy = new ArrayList<>(shapes);
        for (HSSFShape shape: copy){
            removeShape(shape);
        }
    }

    /**
     * The top left x coordinate of this group.
     */
    public int getX1() {
        return _spgrRecord.getRectX1();
    }

    /**
     * The top left y coordinate of this group.
     */
    public int getY1() {
        return _spgrRecord.getRectY1();
    }

    /**
     * The bottom right x coordinate of this group.
     */
    public int getX2() {
        return _spgrRecord.getRectX2();
    }

    /**
     * The bottom right y coordinate of this group.
     */
    public int getY2() {
        return _spgrRecord.getRectY2();
    }

    /**
     * Count of all children and their childrens children.
     */
    public int countOfAllChildren() {
        int count = shapes.size();
        for (HSSFShape shape : shapes) {
            count += shape.countOfAllChildren();
        }
        return count;
    }

    @Override
    void afterInsert(HSSFPatriarch patriarch){
        EscherAggregate agg = patriarch.getBoundAggregate();
        EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
        agg.associateShapeToObjRecord(containerRecord.getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord());
    }

    @Override
    void setShapeId(int shapeId){
        EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
        EscherSpRecord spRecord = containerRecord.getChildById(EscherSpRecord.RECORD_ID);
        spRecord.setShapeId(shapeId);
        CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0);
        cod.setObjectId((short) (shapeId % 1024));
    }

    @Override
    int getShapeId(){
        EscherContainerRecord containerRecord = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
        return ((EscherSpRecord)containerRecord.getChildById(EscherSpRecord.RECORD_ID)).getShapeId();
    }

    @Override
    protected HSSFShape cloneShape() {
        throw new IllegalStateException("Use method cloneShape(HSSFPatriarch patriarch)");
    }

    protected HSSFShape cloneShape(HSSFPatriarch patriarch) {
        EscherContainerRecord spgrContainer = new EscherContainerRecord();
        spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER);
        spgrContainer.setOptions((short) 0x000F);
        EscherContainerRecord spContainer = new EscherContainerRecord();
        EscherContainerRecord cont = getEscherContainer().getChildById(EscherContainerRecord.SP_CONTAINER);
        byte [] inSp = cont.serialize();
        spContainer.fillFields(inSp, 0, new DefaultEscherRecordFactory());

        spgrContainer.addChildRecord(spContainer);
        ObjRecord obj = null;
        if (null != getObjRecord()){
            obj = (ObjRecord) getObjRecord().cloneViaReserialise();
        }

        HSSFShapeGroup group = new HSSFShapeGroup(spgrContainer, obj);
        group.setPatriarch(patriarch);

        for (HSSFShape shape: getChildren()){
            HSSFShape newShape;
            if (shape instanceof HSSFShapeGroup){
                newShape = ((HSSFShapeGroup)shape).cloneShape(patriarch);
            } else {
                newShape = shape.cloneShape();
            }
            group.addShape(newShape);
            group.onCreate(newShape);
        }
        return group;
    }

    public boolean removeShape(HSSFShape shape) {
        boolean  isRemoved = getEscherContainer().removeChildRecord(shape.getEscherContainer());
        if (isRemoved){
            shape.afterRemove(this.getPatriarch());
            shapes.remove(shape);
        }
        return isRemoved;
    }

    @Override
    public Iterator<HSSFShape> iterator() {
        return shapes.iterator();
    }
}
