/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package shape;

import java.awt.*;
import java.io.*;
import java.text.*;
import DrawTop.*;
import menu.*;
import util.*;


public class PaintStyle implements Serializable{
    ShapeContainer shapeContainer=null;
    public Color fillColor=null;
    public Color lineColor=Color.BLACK;
    public float lineWidth=1f;
    public String dashedStyle="solid";
    public float[] dash=null;
    public int arrowStyle=1;
    public int startArrowType=0;
    public int endArrowType=0;

// for debug trace
    static int debug=ShapeContainer.debug;

    public PaintStyle(ShapeContainer shapeContainer){
        this.shapeContainer=shapeContainer;
    }

    public ShapeContainer getShapeContainer(){
        return this.shapeContainer;
    }

//ShapeElement
    public void setShapeContainer(ShapeContainer container){
         this.shapeContainer=container;
         if(container.getPaintStyle()==null||!container.getPaintStyle().equals(this)) {
             container.setPaintStyle(this);
         }
    }

    public void setFillColor(Color fillColor){
        this.fillColor=fillColor;
        //this.getShapeContainer().setChangeCode(UndoConstants.PAINTSTYLE);
    }

    public Color getFillColor(){
        if(this.fillColor!=null&&this.shapeContainer!=null&&this.shapeContainer.isHighlighting()){
            return this.getHighlightColor(this.fillColor, 5f);
        } else {
            return this.fillColor;
        }
    }
    
    public void setLineColor(Color lineColor){
        this.lineColor=lineColor;
    }

    public Color getLineColor(){
        Color lineColor=this.lineColor;
        if(this.shapeContainer!=null&&this.shapeContainer.isHighlighting()){
            if(lineColor==null) lineColor=Color.DARK_GRAY;
            if(this.lineColor!=null&&this.fillColor!=null
                    &&lineColor.equals(this.fillColor)) lineColor=Color.DARK_GRAY;
            lineColor=this.getHighlightColor(lineColor, 5f);
        }
        return lineColor;
    }
    
    private Color getHighlightColor(Color color, float strength){
        //0<=strength<=10
        int step=10;
        if(strength>(float)step) strength=(float)step;
        int r0=color.getRed();
        int g0=color.getGreen();
        int b0=color.getBlue();
        float rd=(255-r0)/(float)step;
        float gd=(255-g0)/(float)step;
        float bd=(255-b0)/(float)step;
        int r=(int)(r0+rd*strength);
        int g=(int)(g0+gd*strength);
        int b=(int)(b0+bd*strength);
        Color newColor=new Color(r, g, b); 
        return newColor;
    }
/*
    private Color getHighlightColor(Color color, float strength){
        float hsbVals[] = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null);
        Color newColor = Color.getHSBColor( hsbVals[0], hsbVals[1], 1.0f/(1f+strength)*(strength + hsbVals[2] ));
        return newColor;
    }
    
 */
    public void setLineWidth(String lineWidth){
        //System.out.println(" -- PaintStyle setLineStyle="+lineStyle);
        String lineWidthStr=lineWidth.replace(" pt", "");
        this.lineWidth=Float.parseFloat(lineWidthStr);
        //this.getShapeContainer().setChangeCode(UndoConstants.PAINTSTYLE);
    }
    
    public String getLineWidthString(){
        NumberFormat nf = NumberFormat.getNumberInstance();
        nf.setMaximumIntegerDigits(1);
        nf.setMinimumFractionDigits(1);
        String str="";
        str+=nf.format(this.lineWidth)+" pt";
        return str;
    }
    
    public float getLineWidth(){
        return this.lineWidth;
    }
    
    public void setDashedStyle(String dashedStyle){
        //System.out.println("setDashedStyle "+dashedStyle);   
        this.dashedStyle=dashedStyle;
        if(dashedStyle.equals("solid")) {
            this.dash=null;
        }
        if(dashedStyle.equals("roundedDot")) {
            float[] dash={0.5f, 2f};
            this.dash=dash;
        }
        if(dashedStyle.equals("squareDot")) {
            float[] dash={1f, 3f};
            this.dash=dash;
        }
        if(dashedStyle.equals("dash")) {
            float[] dash={4f, 4f};
            this.dash=dash;
        }
        if(dashedStyle.equals("dashDot")) {
            float[] dash={4f, 4f, 1f, 4f};
            this.dash=dash;
        }
       if(dashedStyle.equals("dashDotDot")) {
            float[] dash={4f, 4f, 1f, 2f, 1f, 4f};
            this.dash=dash;
        }
        //this.getShapeContainer().setChangeCode(UndoConstants.PAINTSTYLE);
    }
    
    public String getDashedStyle(){
        if(this.dashedStyle.equals("")) this.dashedStyle="solid";
        return this.dashedStyle;
    }
    
    public Stroke getLineStroke(){
        float[] lineDash=null;
        float lineWdth=this.lineWidth;
        if(this.shapeContainer.isHighlighting()){
            if(this.lineWidth<1f) lineWdth=5f*this.lineWidth;  //2.5f
            if(this.lineWidth>=1f) lineWdth=3f*this.lineWidth; // 3f-4.5f
            if(this.lineWidth>=2f) lineWdth=2.5f*this.lineWidth; // 5f-6.25f
            if(this.lineWidth>=3f) lineWdth=2.33f*this.lineWidth; // 7f-
        }
        if(this.dash!=null){
            lineDash=new float[this.dash.length];
            float lineW=this.lineWidth;
            if(lineW<2f) lineW=2f;
            for(int i=0;i<this.dash.length;i++) {
                lineDash[i]=this.dash[i]*lineW;
            }
        }
        BasicStroke stroke=new BasicStroke(lineWdth, BasicStroke.CAP_SQUARE, 
                    BasicStroke.JOIN_MITER, 10.0f, lineDash, 0.0f);
        return stroke;
    }

    public void setArrowStyle(String arrowStyleString){
        String str=arrowStyleString.replace("arrow style", "");
        str=str.replace(" ","");
        this.arrowStyle=Integer.parseInt(str);
        this.startArrowType=0;
        this.endArrowType=0;
        switch(arrowStyle){
            case 1:{
                this.startArrowType=0; this.endArrowType=0;
                break;}
            case 2:{
                this.startArrowType=0; this.endArrowType=1;
                break;}
            case 3:{
                this.startArrowType=1; this.endArrowType=0;
                break;}
            case 4:{
                this.startArrowType=1; this.endArrowType=1;
                break;}
            case 5:{
                this.startArrowType=0; this.endArrowType=2;
                break;}
            case 6:{
                this.startArrowType=2; this.endArrowType=0;
                break;}
            case 7:{
                this.startArrowType=2; this.endArrowType=2;
                break;}
        }
        //this.getShapeContainer().setChangeCode(UndoConstants.PAINTSTYLE);
    }

    public String getArrowStyle(){
        return "arrow style "+String.valueOf(this.arrowStyle);
    }

    public Stroke getArrowStroke(){
        BasicStroke arrowStroke=new BasicStroke(this.lineWidth, BasicStroke.CAP_ROUND, 
                    BasicStroke.CAP_ROUND, 10.0f);
        return arrowStroke;
    }

    public SerializablePaintStyle getSerializablePaintStyle(){
        SerializablePaintStyle  data=new SerializablePaintStyle ();
        data.shapeId=this.getShapeContainer().getShapeId();
        data.fillColor=this.fillColor;
        data.lineColor=this.lineColor;
        data.lineWidth=this.lineWidth;
        data.dashedStyle=this.dashedStyle;
        data.dash=this.dash;
        data.arrowStyle=this.arrowStyle;
        data.startArrowType=this.startArrowType;
        data.endArrowType=this.endArrowType;
        return data;
    }
    
    public void setSerializablePaintStyle(SerializablePaintStyle  data){
        this.fillColor=data.fillColor;
        this.lineColor=data.lineColor;
        this.lineWidth=data.lineWidth;
        this.dashedStyle=data.dashedStyle;
        this.dash=data.dash;
        this.arrowStyle=data.arrowStyle;
        this.startArrowType=data.startArrowType;
        this.endArrowType=data.endArrowType;
    }
    
    public String toString(){
        String str="";
        String shapeElementStr="null";
        if(this.shapeContainer!=null) shapeElementStr=this.shapeContainer.getShapeId();
        str+="PaintStyle shapeElement="+shapeElementStr+
                "\n  - fillColor="+this.fillColor+", lineColor="+this.lineColor+
                ", lineWidth="+this.getLineWidthString()+
                ", dashedStyle="+this.getDashedStyle()+", arrowStyle="+this.arrowStyle+
                ", start arrow type="+this.startArrowType+", end arrow type="+this.endArrowType;
 
        return str;
    }
    
    public String toShortString(){
        String str="";
        str+="PaintStyle  fillColor="+this.fillColor+", lineColor="+this.lineColor+
                ", lineWidth="+this.getLineWidthString()+
                ", dashedStyle="+this.getDashedStyle()+", arrowStyle="+this.arrowStyle+
                ", start arrow type="+this.startArrowType+", end arrow type="+this.endArrowType;
 
        return str;
    }

    public Object clone(){
        PaintStyle paintStyle=new PaintStyle(null);
        Color color=this.fillColor;
        if(this.fillColor==null) paintStyle.fillColor=null;
        else paintStyle.fillColor
                =new Color(color.getRed(), color.getGreen(), color.getBlue());

        color=this.lineColor;
        if(this.lineColor==null) paintStyle.lineColor=null;
        else paintStyle.lineColor
                =new Color(color.getRed(), color.getGreen(), color.getBlue());
                
        paintStyle.lineWidth=this.lineWidth;
        paintStyle.dashedStyle=new String(this.dashedStyle);
        paintStyle.dash=null;
        if(this.dash!=null){
            float[] dash=new float[this.dash.length];
            for(int i=0;i<this.dash.length;i++) dash[i]=this.dash[i];
            paintStyle.dash=dash;
        }
        paintStyle.arrowStyle=this.arrowStyle;
        paintStyle.startArrowType=this.startArrowType;
        paintStyle.endArrowType=this.endArrowType;
        return paintStyle;
    }
   
    public static Stroke getDefaultStroke(){
        BasicStroke defaultStroke=new BasicStroke(0.5f, BasicStroke.CAP_SQUARE, 
                    BasicStroke.JOIN_MITER, 10.0f);
    return defaultStroke;
    }
    
    public static Stroke getDefaultStroke(float lineWidth){
        BasicStroke defaultStroke=new BasicStroke(lineWidth, BasicStroke.CAP_SQUARE, 
                    BasicStroke.JOIN_MITER, 10.0f);
    return defaultStroke;
    }
    
    
    public static void setPaintStyleToMenu(ShapeContainer[] shapeContainers, String callFrom){
        MenuUtil menuUtil=ObjectTable.getMenuUtil();
        PaintStyle paintStyle=getCommonPaintStyle(shapeContainers);
        if(debug>0) System.out.println("- paintStyle.setPaintStyleToMenu callFrom=" 
                    +callFrom+", paintStyle "+paintStyle.toString());
        Component[] fillColorChoosers
                =menuUtil.getMenuComponents(Command.getCommandString(Command.FILL_COLOR));
        Component[] lineColorChoosers
                =menuUtil.getMenuComponents(Command.getCommandString(Command.LINE_COLOR));
        Component[] lineStyleButtons
                =menuUtil.getMenuComponents(Command.getCommandString(Command.LINE_WIDTH));
        Component[] dashedStyleButtons
                =menuUtil.getMenuComponents(Command.getCommandString(Command.LINE_STROKE));
        Component[] arrowStyleButtons
                =menuUtil.getMenuComponents(Command.getCommandString(Command.ARROW_STYLE));

        Color currentColor=paintStyle.getFillColor();
        CustomColorChooserDialog dialog=ObjectTable.getCustomColorChooserDialog();
        dialog.setPreviewColor(currentColor, "fill color");

        currentColor=paintStyle.getLineColor();
        dialog.setPreviewColor(currentColor, "line color");
        
        for(int i=0;i<lineStyleButtons.length;i++){
                ButtonOfPulldownMenu pullDownMenuButton=(ButtonOfPulldownMenu)lineStyleButtons[i];
                pullDownMenuButton.setSelectedMenuItem(paintStyle.getLineWidthString());
        }
        for(int i=0;i<dashedStyleButtons.length;i++){
                ButtonOfPulldownMenu pullDownMenuButton=(ButtonOfPulldownMenu)dashedStyleButtons[i];
                pullDownMenuButton.setSelectedMenuItem(paintStyle.getDashedStyle());
        }
        for(int i=0;i<lineStyleButtons.length;i++){
                ButtonOfPulldownMenu pullDownMenuButton=(ButtonOfPulldownMenu)arrowStyleButtons[i];
                pullDownMenuButton.setSelectedMenuItem(paintStyle.getArrowStyle());
        } // for
    }//setPaintStyleToMenu
    
    public static PaintStyle getCommonPaintStyle(ShapeContainer[] shapeContainers){
        PaintStyle outputPaintStyle=new PaintStyle(null);
        Color commonFillColor=null;
        Color commonLineColor=null;
        float commonLineWidth=-1.0f;
        String commonDashedStyle="";
        float[] commonDash=null;
        int commonArrowStyle=-1;
        int size=0;
        if(shapeContainers!=null&&shapeContainers.length>0) {
            size=shapeContainers.length;
            PaintStyle paintStyle=shapeContainers[0].getPaintStyle();
            commonFillColor=paintStyle.fillColor;
            commonLineColor=paintStyle.lineColor;
            commonLineWidth=paintStyle.lineWidth;
            commonDashedStyle=paintStyle.dashedStyle;
            commonDash=paintStyle.dash;
            commonArrowStyle=paintStyle.arrowStyle;
        }
        for(int i=1;i<size;i++){
            PaintStyle paintStyle=shapeContainers[i].getPaintStyle();
            Color fillColor=paintStyle.fillColor;
            Color lineColor=paintStyle.lineColor;
            float lineWidth=paintStyle.lineWidth;
            String dashedStyle=paintStyle.dashedStyle;
            float[] dash=paintStyle.dash;
            int arrowStyle=paintStyle.arrowStyle;
            if(fillColor==null) commonFillColor=null;
            else if(!fillColor.equals(commonFillColor)) commonFillColor=null;
            if(lineColor==null) commonLineColor=null;
            else if(!lineColor.equals(commonLineColor)) commonLineColor=null;
            if(lineWidth!=commonLineWidth) commonLineWidth=-1.0f;
            if(!dashedStyle.equals(commonDashedStyle)) commonDashedStyle="";
            if(dash==null) commonDash=null;
            else if(!dash.equals(commonDash)) commonDash=null;
            if(arrowStyle!=commonArrowStyle) commonArrowStyle=-1;
        }
        if(commonLineWidth<0) commonLineWidth=0.5f;
        if(commonDashedStyle.equals("")) commonDashedStyle="solid";
        if(commonArrowStyle<0) commonArrowStyle=0;
        outputPaintStyle.fillColor=commonFillColor;
        outputPaintStyle.lineColor=commonLineColor;
        outputPaintStyle.lineWidth=commonLineWidth;
        outputPaintStyle.dashedStyle=commonDashedStyle;
        outputPaintStyle.dash=commonDash;
        outputPaintStyle.arrowStyle=commonArrowStyle;
        if(debug>0) System.out.println("- PaintStyle.getCommonPaintStyle" +
                    ", paintStyle="+outputPaintStyle.toString());
         return outputPaintStyle;
    }
}