package myuml;

import com.borland.jbcl.layout.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import com.umlet.control.Constants;
import java.io.Serializable;
import java.util.ArrayList;
import java.awt.BasicStroke;
import java.awt.Font;
import java.awt.FontMetrics;
import java.util.Map;

/**
 * <p>Title: Generación de Coreografías de Servicios Web</p>
 *
 * <p>Description:Clase que gestiona el dibujado de los mensajes que
 * intervienen en el diagrama </p>
 *
 * <p>Copyright: Copyright (c) 2007</p>
 *
 * <p>Company: UCLM</p>
 *
 * @version 1.0
 */
public class MyMessage extends MyObjects  implements Serializable{
    //Atributo para controlar el dibujado del mensaje, si va hacia la izquierda
    //o hacia la derecha.
    public boolean inverted;
    //Creamos objetos para identificar el destino y el origen de los mensajes
    public MyObjects source, dest;

    //Actualizaciones de variables asociadas al objeto
    public ArrayList updates;

    //Booleano para indicar si se trata de un mensaje asíncrono
    public boolean asin;

    //String con el timeout
    protected String timeout = "";

    //String con el clock del timeout
    protected String timeout_clock = "";

    //String con la excepción que puede generar
    protected String exception_variable = "";

    //String con la variable que se envía
    protected String send_variable = "";

    //String con la variable en que se recibe
    protected String receive_variable = "";

    /**
    * Crea un mensaje
    *
    * @param c Coordenadas del mensaje
    */
    public MyMessage(XYConstraints c, boolean asyn) {
        super(c);
        inverted = false;
        source = null;
        dest = null;
        updates = new ArrayList();
        asin = asyn;
    }

    /**
     * Método que devuelve el identificador del origen del mensaje
     *
     * @return MyObjects Devuelve un objeto que puede ser de tipo 'Actor' o de tipo
     *   'Lifeline'
     */
    public String getSource(){
        return source.getID();
    }

    /**
     * Método que devuelve el identificador del destino del mensaje
     *
     * @return MyObjects devuelve un objeto que puede ser de tipo 'Actor' o de
     *   tipo 'Lifeline'
     */
    public String getDest(){
        return dest.getID();
    }

    public ArrayList getUpdates(){

        return updates;

    }

    public void setUpdates(ArrayList up){

        updates = up;

    }

    /**
     * Método que devuelve si el mensaje es asíncrono
     *
     * @return asin del mensaje
     */
    public boolean getAsin(){
        return asin;
    }


    /**
     * Método que establece la variable booleana asin del mensaje
     *
     * @param asyn del mensaje
     */
    public void setAsin(boolean asyn){
        asin = asyn;
    }

    /**
     * Método que permite asociar un timeout al mensaje
     *
     * @param s timeout del mensaje
     */
    public void setTimeout(String s){
        timeout = s;
    }

    /**
     * Método que devuelve el timeout asociado al mensaje
     *
     * @return timeout del mensaje
     */
    public String getTimeout(){
        return timeout;
    }


    /**
     * Método que permite asociar un reloj al timeout al mensaje
     *
     * @param s reloj timeout del mensaje
     */
    public void setTimeout_clock(String s){
        timeout_clock = s;
    }

    /**
     * Método que devuelve el reloj del timeout asociado al mensaje
     *
     * @return reloj timeout del mensaje
     */
    public String getTimeout_clock(){
        return timeout_clock;
    }

    /**
     * Método que permite asociar una excepción al mensaje
     *
     * @param s excepción del mensaje
     */
    public void setException_variable(String s){
        exception_variable = s;
    }

    /**
     * Método que devuelve la excepción asociada al mensaje
     *
     * @return excepcion del mensaje
     */
    public String getException_variable(){
        return exception_variable;
    }

    /**
     * Método que permite asociar una variable enviada al mensaje
     *
     * @param s variable enviada
     */
    public void setSend_variable(String s){
        send_variable = s;
    }

    /**
     * Método que devuelve la variable enviada por el mensaje
     *
     * @return variable enviada
     */
    public String getSend_variable(){
        return send_variable;
    }

    /**
     * Método que permite asociar una variable que recibe al mensaje
     *
     * @param s variable que recibe
     */
    public void setReceive_variable(String s){
        receive_variable = s;
    }

    /**
     * Método que devuelve la variable que recibe del mensaje
     *
     * @return variable que recibe
     */
    public String getReceive_variable(){
        return receive_variable;
    }

    /**
     * Método que dibuja los mensajes, siempre que tengamos definidos un origen
     * y un destino
     *
     * @param g parámetro que contiene métodos para dibujar el mensaje
     */
    public void paint(Graphics g) {

        if(source==null || dest==null) return;

        if(xyc.getWidth()<0){
            inverted = true;
            xyc.setWidth(-xyc.getWidth());
            setSize(xyc.getWidth(),xyc.getHeight());
        }

        Graphics2D g2 = (Graphics2D) g;

        g2.setColor(col);

        if(name!=""){

            int yPos=18;

            String show_message = "Exception";

            if(timeout.compareTo("")!=0){
                show_message=show_message + " ["+timeout_clock+" <= "+timeout+"]";
            }

            if(exception_variable.compareTo("")!=0){
                show_message=show_message + " ["+exception_variable+"]";
            }

            //Pintar frame si hay excepción o timeout
            if(timeout.compareTo("")!=0 || exception_variable.compareTo("")!=0){

                //Pintar excepción
                Font f_old = g2.getFont();
                Font f_new = new Font(f_old.getName(), f_old.getStyle(), 9);
                FontMetrics fm = g2.getFontMetrics(f_new);
                int string_width = fm.stringWidth(show_message);

                //Rectángulo que contiene la excepción
                g2.drawRect(10, 0, string_width + 20, 18);

                g2.drawRect(10, 0, string_width + 20, 10);

                //Cadena con la excepción
                g2.drawString(show_message, 13, 9);

                //Línea uniendo al mensaje
                g2.drawLine(string_width + 35,xyc.getHeight()-6,string_width + 30,10);

                //Círculo donde se pinta la línea del mensaje a la excepción
                g2.drawOval(string_width + 32,xyc.getHeight()-9,6,6);

                //Recuperar antigua fuente
                g2.setFont(f_old);

            }

            Constants.write(g2, name, this.getWidth() / 2, yPos, true);

        }

        int endx = getWidth()-1;
        int posy = xyc.getHeight()-6;

        //Pintar con línea continua o discontinua dependiendo de si el mensaje
        //es asíncrono o asíncrono

        if(!asin){
            g.drawLine(0, posy, endx, posy);
        }

        else{

            float dash1[] = {15.0f};
            BasicStroke dashed = new BasicStroke(1.0f,
                                      BasicStroke.CAP_BUTT,
                                      BasicStroke.JOIN_MITER,
                                      10.0f, dash1, 0.0f);
            g2.setStroke(dashed);

            g2.drawLine(0, posy, endx, posy);
        }
        // Sincrono
        if(!inverted){
            int[] xs = {endx, endx - 5, endx - 5};
            int[] ys = {posy, posy - 5, posy + 5};
            Polygon p = new Polygon(xs, ys, 3);
            g.drawPolygon(p);
            g.fillPolygon(p);
        }
        else{
            int[] xs = {0, 5, 5};
            int[] ys = {posy, posy - 5, posy + 5};
            Polygon p = new Polygon(xs, ys, 3);
            g.drawPolygon(p);
            g.fillPolygon(p);
            //inverted = false;
            //xyc.setWidth(-xyc.getWidth());
        }

    }
}
