package shape;

import java.awt.*;
import java.awt.geom.*;
import java.io.*;
import java.util.*;
import DrawTop.*;
import textBox.*;
import geomExtension.*;
import util.*;

public class SerializableElementUtil implements Serializable {

    public static final String[] versions={"ver0.0", "ver1.0"};
    static int debug=0;
	
	public static SerializableElement convertShapeContainer(ShapeContainer container) {
		SerializableElement sElement = null;
		if (container.getContainerType() == ShapeContainer.SHAPE) {
			sElement = convertSingleContainer(container);
			//sElement = convertContainerSimply(container);
		} else {
			sElement = convertGroupContainer(container);
			//sElement = convertGroupContainer_org(container);
		}
		return sElement;
	}

	public static SerializableElement convertSingleContainer(ShapeContainer container) {
		SerializableElement sElement = new SerializableElement();
		//sElement for a sigle shape ShapeContainer
		sElement.containerType = ShapeContainer.SHAPE;
		sElement.containerIndex = container.getContainerIndex();
		ShapeContainer parent = container.getParent();
		sElement.parent = "";
		if (parent != null) {
			sElement.parent = parent.getShapeId();
		}
		sElement.shapeId = container.getShapeId();
		sElement.date = Calendar.getInstance().getTime();
		sElement.fileNameAndPage = ObjectTable.getFileIo().getCurrentFileName()
				+ ":" + ObjectTable.getFileIo().getCurrentPage();
		sElement.connectorTargetPermission = container.connectorTargetPermission;
		sElement.connectorPermission = container.connectorPermission;
		sElement.property = container.property;

		//sElement for shapeElement
		ShapeElement shapeElement = container.getElement();
		int tye = shapeElement.getTypeE();
		sElement.elementType = Command.getCommandString(tye);
		//sElement.elementType=shapeElement.getTypeE();
		sElement.serializableCurve2D = shapeElement.getSerializableCurve2D();
		//sElement for PaintStyle
		sElement.fillColor = container.getPaintStyle().fillColor;
		sElement.lineColor = container.getPaintStyle().lineColor;
		sElement.lineWidth = container.getPaintStyle().lineWidth;
		sElement.dashedStyle = container.getPaintStyle().dashedStyle;
		sElement.dash = container.getPaintStyle().dash;
		sElement.arrowStyle = container.getPaintStyle().arrowStyle;
		sElement.startArrowType = container.getPaintStyle().startArrowType;
		sElement.endArrowType = container.getPaintStyle().endArrowType;
		// sElement for TextBox only
		if (container.isTextBox()) {
			TextBox textBox = container.getTextBox();
			sElement.textArea = (Rectangle2D) textBox.textArea.clone();
			CommittedTextContainer committedTextContainer = textBox.getCommittedTextContainer();
			sElement.attributedString = committedTextContainer.getSerializableAttributedString();
			sElement.textBoxInsets = (Insets) textBox.textBoxInsets.clone();
			sElement.textAlign = textBox.textAlign;
			sElement.lineSpace = textBox.lineSpace;
		}
		// sElement for ImageElement
		if (sElement.elementType.equalsIgnoreCase("IMAGE")) {
			ImageElement imageElement = (ImageElement) shapeElement;
			sElement.imageByteData = imageElement.getByteImage();
		}

		return sElement;
	}

	private static SerializableElement convertGroupContainer(ShapeContainer container) {
		SerializableElement sElement = new SerializableElement();
		//ShapeElement shapeElement = container.getElement();
		GroupElement groupElement=(GroupElement)container.getElement();
		//sElement for group ShapeContainer
		sElement.containerType = ShapeContainer.GROUP;
		sElement.containerIndex = container.getContainerIndex();
		ShapeContainer parent = container.getParent();
		sElement.parent = "";
		if (parent != null) {
			sElement.parent = parent.getShapeId();
		}
		int tye = groupElement.getTypeE();
		sElement.elementType = Command.getCommandString(tye);
		//sElement.elementType=groupElement.getTypeE();
		sElement.shapeId = container.getShapeId();
		sElement.date = Calendar.getInstance().getTime();
		sElement.fileNameAndPage = ObjectTable.getFileIo().getCurrentFileName()
				+ ":" + ObjectTable.getFileIo().getCurrentPage();
		sElement.connectorTargetPermission = container.connectorTargetPermission;
		sElement.connectorPermission = container.connectorPermission;
		sElement.property = container.property;

		ShapeContainer[] children = groupElement.getChildren();
		sElement.childrenList.clear();
		for (int i = 0; i < children.length; i++) {
				ShapeContainer child = (ShapeContainer) children[i];
				SerializableElement sChild = convertShapeContainer(child);
				sElement.childrenList.add(sChild);
				if (debug > 0) {
					System.out.println(" convertGroupContainer add to childrenList"
							+ " sChild[" + i + "]=" + sChild.shapeId + ", Parent=" + container.getShapeId());
				}
		}
		return sElement;
	}

	public static ShapeContainer invertShapeContainer(SerializableElement sElement) {
		//public static ShapeContainer reconstructShapeContainer(SerializableElement sElement){
		ShapeContainer container = null;
		if (sElement.containerType == ShapeContainer.SHAPE) {
			container = invertSingleContainer(sElement);
			if (container != null) {
				container.setSelected(false);
			}
		} else {
			container = invertGroupContainer(sElement);
			container.setSelected(false);
		}
		if (debug > 0) {
			System.out.println("\n** SerializableElementUtil invertShapeContainer **" + "\n"
					+ "- SerializableElementUtil" + sElement.toShortString()
					+ "\n- ShapeContainer" + container.toShortString());
		}
		return container;
	}

	public static ShapeContainer invertSingleContainer(SerializableElement sElement) {
		//public static ShapeContainer invertContainerSimply(SerializableElement sElement) {
		ShapeContainer container = new ShapeContainer();
		container.setContainerIndex(sElement.containerIndex);
		ShapeElement shapeElement = null;
		String shapeId = sElement.shapeId;
		int id = container.getElementType(shapeId);
		int type = Command.getCommandId(sElement.elementType);
		if (type < 0) {
			System.err.println("*** Error invertSingleContainerSimply: id=" + type
					+ ", elementType=" + sElement.elementType);
			type = id;
		}
		switch (type) {
			case Command.RECTANGLE: {
				shapeElement = new RectangleElement();
				break;
			}
			case Command.ROUND_RECTANGLE: {
				shapeElement = new RoundRectangleElement();
				break;
			}
			case Command.ELLIPSE: {
				shapeElement = new EllipseElement();
				break;
			}
			case Command.LINE: {
				shapeElement = new LineElement();
				break;
			}
			case Command.POLYLINE: {
				shapeElement = new PolylineElement();
				break;
			}
			case Command.CUBIC_CURVE: {
				shapeElement = new CubicCurveElement();
				break;
			}
			case Command.GENERAL_CURVE: {
				shapeElement = new GeneralCurveElement();
				break;
			}

			case Command.IMAGE: {
				shapeElement = new ImageElement();
				ImageElement imageElement = (ImageElement) shapeElement;
				imageElement.setByteImage(sElement.imageByteData);
				break;
			}
		} //switch
		// set ShapeContainer sElement
		container.setShapeId(sElement.shapeId);
		container.setElement(shapeElement);
		shapeElement.setShapeContainer(container);
		container.setConnectorTargetPermission(sElement.connectorTargetPermission);
		container.setConnectorPermission(sElement.connectorPermission);
		container.property = sElement.property;
		container.property.put("type", shapeElement.getShapeIdString());
		// set ShapeElement sElement
		shapeElement.setSerializableCurve2D((SerializableCurve2D) sElement.serializableCurve2D.clone());

		// set PaintStyle sElement
		PaintStyle paintStyle = container.getPaintStyle();
		//PaintStyle paintStyle=new PaintStyle(container);
		paintStyle.fillColor = sElement.fillColor;
		paintStyle.lineColor = sElement.lineColor;
		paintStyle.lineWidth = sElement.lineWidth;
		paintStyle.dashedStyle = sElement.dashedStyle;
		paintStyle.dash = sElement.dash;
		paintStyle.arrowStyle = sElement.arrowStyle;
		paintStyle.startArrowType = sElement.startArrowType;
		paintStyle.endArrowType = sElement.endArrowType;
		container.setPaintStyle(paintStyle);
		// set textBox
		if (sElement.textArea != null) {
			Rectangle2D textArea = (Rectangle2D) sElement.textArea.clone();
			container.addTextBox(textArea);
			TextBox textBox = container.getTextBox();
			textBox.setTextArea(textArea);
			CommittedTextContainer committedTextContainer
					= textBox.getCommittedTextContainer();
			committedTextContainer.setSerializableAttributedString(sElement.attributedString);
			textBox.textBoxInsets = (Insets) sElement.textBoxInsets.clone();
			textBox.textAlign = sElement.textAlign;
			textBox.lineSpace = sElement.lineSpace;
		}

		if (debug > 0) {
			System.out.println(" ++ OutputElementData.createShapeContainer "
					+ "container=" + container.toString());
		}
		return container;
	}

	public static ShapeContainer invertGroupContainer(SerializableElement sElement) {
		if (debug > 0) {
			System.out.println("\n** SerializableElementUtil invertGropShapeContainer **" + "\n"
					+ "- SerializableElementUtil" + sElement.toString());
		}
		ShapeContainer container = new ShapeContainer();
		container.setContainerIndex(sElement.containerIndex);
		container.setShapeId(sElement.shapeId);
		container.setConnectorTargetPermission(sElement.connectorTargetPermission);
		container.setConnectorPermission(sElement.connectorPermission);
		container.property = sElement.property;
		GroupElement groupElement = new GroupElement();
		container.setElement(groupElement);
		groupElement.setShapeContainer(container);
		if (debug > 0) {
			System.out.println(" ++ SerializableElementUtil.invertGropShapeContaine "
					+ "groupContainer=" + container.toString());
		}

		ArrayList childrenList = (ArrayList) sElement.childrenList.clone();
		for (int j = 0; j < childrenList.size(); j++) {
			String className = childrenList.get(j).getClass().getSimpleName();
			if (debug > 0) {
				System.out.println(" ++ SerializableElementUtil.convertToGroupContainer "
						+ "loop j=" + j + ", className=" + className);
			}
			//className equals String in DrawFileIo
			if (!className.equals("String")) {
				//className=="SerializableElement"
				SerializableElement childData = (SerializableElement) childrenList.get(j);
				//----------------------------------------------//
				ShapeContainer childContainer
						= invertShapeContainer(childData);
				//----------------------------------------------//  
				if (childContainer != null) {
					groupElement.addChildren(childContainer);
					childContainer.setParent(container);
				}
			}
		}
		if (debug > 0) {
			System.out.println("\n** SerializableElementUtil invertGropShapeContainer **" + "\n"
					+ "- ShapeContainer" + container.toShortString());
		}

		return container;
	}

     public static void setToShapeContainer(SerializableElement sElement, ShapeContainer container){
         if(container.getContainerType()==ShapeContainer.GROUP){
             setToGroupContainer(sElement, container);
         } else{
             setToSingleShapeContainer(sElement, container);
         }
         container.setSelected(false);
     }
    
	private static void setToGroupContainer(SerializableElement sElement,
			ShapeContainer container) {
		int debug = FileIo.debug;
		container.setContainerIndex(sElement.containerIndex);
		GroupElement groupElement = (GroupElement) container.getElement();
		container.setElement(groupElement);
		groupElement.setShapeContainer(container);
		//groupElement.
		container.setShapeId(sElement.shapeId);
		ArrayList childrenList = groupElement.getChildrenList();
		ArrayList sChildrenList = (ArrayList) sElement.childrenList.clone();
		for (int j = 0; j < sChildrenList.size(); j++) {
			SerializableElement sChildData = (SerializableElement) sChildrenList.get(j);
			ShapeContainer child = (ShapeContainer) childrenList.get(j);
			setToShapeContainer(sChildData, child);
		}
		if (debug > 0) {
			System.out.println(" ++ setToGroupContainer "
					+ "groupContainer=" + container.toString());
		}
		return;
	}
 
    private static void setToSingleShapeContainer(SerializableElement sElement,
            ShapeContainer container){
// set ShapeContainer sElement
        container.setShapeId(sElement.shapeId);
        container.setContainerIndex(sElement.containerIndex);
        container.setConnectorTargetPermission(sElement.connectorTargetPermission);
        container.setConnectorPermission(sElement.connectorPermission);
        container.property=sElement.property;
        
// set ShapeElement sElement
         ShapeElement shapeElement=null;
         String shapeId=sElement.shapeId;
         int id=container.getElementType(shapeId);
         int type=Command.getCommandId(sElement.elementType);
         if(type<0){
             System.err.println("*** Error SerializableElementUtil.setToSingleContainer: id="+type+
                      ", elementType="+sElement.elementType);
             type=id;
         }
         switch(type){
            case Command.RECTANGLE :{ 
                shapeElement=new RectangleElement(); break;
            }
            case Command.ROUND_RECTANGLE:{ 
                shapeElement=new RoundRectangleElement(); break;
            }
            case Command.ELLIPSE:{ 
                shapeElement=new EllipseElement(); break;
            }
            case Command.LINE: {
                shapeElement=new LineElement();
                break;
            }
            case Command.POLYLINE:{ 
                shapeElement=new PolylineElement();
                break;
            }
            case Command.CUBIC_CURVE:{ 
                shapeElement=new CubicCurveElement();
                break;
            }
            case Command.GENERAL_CURVE:{ 
                shapeElement=new GeneralCurveElement();
                break;
            }
            case Command.IMAGE:{ 
                shapeElement=new ImageElement();
                ImageElement imageElement=(ImageElement)shapeElement;
                imageElement.setByteImage(sElement.imageByteData);
                break;
            }
        } //switch
// set ShapeElement sElement
        container.setElement(shapeElement);
        shapeElement.setShapeContainer(container);
        shapeElement.setSerializableCurve2D((SerializableCurve2D)sElement.serializableCurve2D.clone());
        

// set PaintStyle sElement
        PaintStyle paintStyle=container.getPaintStyle();
        paintStyle.fillColor=sElement.fillColor;
        paintStyle.lineColor=sElement.lineColor;
        paintStyle.lineWidth=sElement.lineWidth;
        paintStyle.dashedStyle=sElement.dashedStyle;
        paintStyle.dash=sElement.dash;
        paintStyle.arrowStyle=sElement.arrowStyle;
        paintStyle.startArrowType=sElement.startArrowType;
        paintStyle.endArrowType=sElement.endArrowType;
        container.setPaintStyle(paintStyle);
// set textBox
        if(sElement.textArea!=null){
            container.addTextBox();
            Rectangle2D textArea=(Rectangle2D)sElement.textArea.clone();
            TextBox textBox=container.getTextBox();
            CommittedTextContainer attributedStringContainer
                        =textBox.getCommittedTextContainer();
            attributedStringContainer.setSerializableAttributedString(sElement.attributedString);
            textBox.setTextArea(textArea);
            textBox.textBoxInsets=(Insets)sElement.textBoxInsets.clone();
            textBox.textAlign=sElement.textAlign;
            textBox.lineSpace=sElement.lineSpace;
        }
        int debug=Edit.debug+FileIo.debug;
        if(debug>0) System.out.println(" ++ OutputElementData.createShapeContainer " +
            "container="+container.toString());
        return ;
    }
}
