<%@page contentType="image/svg+xml;charset=UTF-8" pageEncoding="ISO-8859-1" session="true"
%><%@page errorPage="Error.jsp"
%><%@page import="com.fujitsu.iflow.model.workflow.WFSession"
%><%@page import="com.fujitsu.iflow.common.UdaNameSanitizer"
%><%@page import="com.fujitsu.iflow.model.util.AEServers"
%><%@page import="com.fujitsu.iflow.model.util.QuickForm"
%><%@page import="com.fujitsu.iflow.model.util.URLEncoder"
%><%@page import="com.fujitsu.iflow.model.workflow.*"
%><%@page import="com.fujitsu.iflow.model.wfcore.*"
%><%@page import="java.awt.Point"
%><%@page import="java.util.*"
%><%@page import="java.io.*"
%><%request.setCharacterEncoding("UTF-8");request.getParameterNames(); //Need dummy call for WL9.1
%><%
    WFSession wfSession = (WFSession)session.getAttribute("ModelsessionID");
    if (wfSession == null) {
        response.sendRedirect(goToLogin(request, "Continue to Process Instance Graphic"));
        return;
    }

    String planIdStr = request.getParameter("planId");
    out.clearBuffer();
    Plan plan = WFObjectFactory.getPlan(Long.parseLong(planIdStr), wfSession);
    int xmax = 290;
    int ymax = 290;

    if (bias == null) {
        bias = new Point[24];
        bias[Node.TYPE_START] = new Point(0,0);
        bias[Node.TYPE_EXIT] = new Point(0,0);
        bias[Node.TYPE_CONDITION] = new Point(18,18);
        bias[Node.TYPE_AND] = new Point(18,18);
        bias[Node.TYPE_OR] = new Point(18,18);
        bias[Node.TYPE_DELAY] = new Point(18,18);
        bias[Node.TYPE_SUB_PROCESS] = new Point(40,25);
        bias[Node.TYPE_CHAINED_PROCESS] = new Point(40,25);
        bias[Node.TYPE_REMOTE_SUB_PROCESS] = new Point(40,25);
        bias[Node.TYPE_VOTING_ACTIVITY] = new Point(0,0);
        bias[Node.TYPE_ACTIVITY] = new Point(0,0);
    }


    Node[] allNodes = plan.getNodes();
    int last = allNodes.length;
    
    getRoles(allNodes, out);
    
    nodesTable =  new Hashtable();
    Enumeration enumRoles = roles.keys();
    
    while (enumRoles.hasMoreElements()) {   
        int count = 0;
        String roleName = (String)enumRoles.nextElement();
        Point sPoint = (Point)roles.get(roleName);                
        for (int i=0; i<last; i++) {
            Point p = new Point();
            Node aNode = allNodes[i];
            Long id = new Long(aNode.getNodeId());
            if((aNode.getType() == Node.TYPE_ACTIVITY) || (aNode.getType() == Node.TYPE_VOTING_ACTIVITY)){
                if(roleName.equals(aNode.getRole())){
                    sPoint.x = (sPoint.x+150);
                    p.x = sPoint.x;
                    p.y = sPoint.y+40;
                    nodesTable.put(id, p);
                    count ++;
                }
            }else
            {
                nodesTable.put(id, aNode.getPosition());
            }
        }

     }
     
    for (int i=0; i<last; i++) {

        Node aNode = allNodes[i];
        Long id = new Long(aNode.getNodeId());
        
        Point p = (Point)nodesTable.get(id);
        if (p.x+60>xmax) xmax = p.x+60;
        if (p.y+45>ymax) ymax = p.y+45;

    }

	System.out.println(" xmax : " + xmax + " ymax :" + ymax);
%><?xml version="1.0" encoding="UTF-8"?>
<svg width="<%=xmax+100%>px" height="<%=ymax+100%>px" overflow="scroll" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <marker id="Triangle" viewBox="0 0 16 16" refX="16" refY="8"
      markerUnits="strokeWidth" markerWidth="6" markerHeight="4"
      orient="auto">
      <path d="M 0 0 L 16 8 L 0 16 z"/>
    </marker>
  </defs>

<%
    Enumeration enumRoles1 = roles.keys();
    while (enumRoles1.hasMoreElements()) {
       
        String roleName1 = (String)enumRoles1.nextElement();
	Point sPoint1 = (Point)roles.get(roleName1);
	sPoint1.x = 0;
	Point ePoint1 = new Point(xmax+350, sPoint1.y);

	drawLine(sPoint1, ePoint1, "fill:black; stroke:black", out);
	System.out.println("sPoint1.x : " + sPoint1.x);
	Point sPoint2 = new Point(0, sPoint1.y+100);
        Point ePoint2 = new Point(xmax+350, ePoint1.y+100);
	drawLine(sPoint2, ePoint2, "fill:black; stroke:black", out);
        drawLine(sPoint1, sPoint2, "fill:black; stroke:black", out);
	drawLine(ePoint1, ePoint2, "fill:black; stroke:black", out);
	sPoint1.x = sPoint1.x + 15;
	sPoint2.x = sPoint2.x + 15;
	drawLine(sPoint1, sPoint2, "fill:black; stroke:black", out);
	drawText(sPoint1.x, sPoint2.y, roleName1, out);

    }
    
    for (int i=0; i<last; i++) {

        Node aNode = allNodes[i];

        Arrow[] az = aNode.getOutgoingArrows();
        int last2 = az.length;
        for (int j=0; j<last2; j++) {
            Arrow aArrow = az[j];

            Point startPoint = aArrow.getStartPoint();
            Point endPoint = aArrow.getEndPoint();
            Point[] pz = aArrow.getPoints();
            if (pz == null) {
                pz = new Point[0];
            }

	    Long id = new Long(aNode.getNodeId());
	    Point aPoint = (Point)nodesTable.get(id);
	    id = new Long(aArrow.getTargetNode().getNodeId());
	    Point sPoint = (Point)nodesTable.get(id);
	    startPoint = calcEndPoint(aPoint, aNode);
	    endPoint = calcEndPoint(sPoint, aArrow.getTargetNode());

            StringBuffer b = new StringBuffer();
            addPoint(b, "M", startPoint);

            int last3 = pz.length;
            for (int k=0; k<last3; k++) {
                Point midPoint = pz[k];
                addPoint(b, "L", midPoint);
                startPoint = midPoint;
            }
            addPoint(b, "L", endPoint);

            drawPath(b.toString(), "fill:none; stroke:lightskyblue; stroke-width:2", out);
            drawText((startPoint.x+endPoint.x)/2,(startPoint.y+endPoint.y)/2,aArrow.getName(), out);
        }
    }

    // now write out all the nodes.
    for (int i=0; i<last; i++) {

        Node aNode = allNodes[i];
        int nodeType = aNode.getType();
        Point bp = bias[nodeType];
        Point ap = aNode.getPosition();
	Long id = new Long(aNode.getNodeId());
        Point aPoint = (Point)nodesTable.get(id);
        //Point aPoint = new Point(ap.x+bp.x, ap.y+bp.y);

        switch (nodeType) {
            case Node.TYPE_START:
                %><circle cx="<%= aPoint.x %>" cy="<%= aPoint.y %>" r="30" style="fill:black; stroke:black"/>
                <text x="<%=aPoint.x-15%>" y="<%=aPoint.y+5%>" style="fill:white">Start</text><%
                break;
            case Node.TYPE_EXIT:
                %><circle cx="<%= aPoint.x %>" cy="<%= aPoint.y %>" r="30" style="fill:black; stroke:black"/>
                <text x="<%=aPoint.x-15%>" y="<%=aPoint.y+5%>" style="fill:white"><% QuickForm.writeHtml(out,aNode.getName()); %></text><%
                break;
            case Node.TYPE_CONDITION:
                %><path d="M <%=aPoint.x-27%> <%=aPoint.y%> l 27 18 l 27 -18 l -27 -18 l -27 18 z"  style="fill:powderblue; stroke:black"/><%
                break;
            case Node.TYPE_AND:
                %><path d="M <%=aPoint.x-18%> <%=aPoint.y-18%> l 9 0 l 9 5 l 9 -5 l 9 0 l 0 9 l -5 9 l 5 9 l 0 9 l -9 0 l -9 -5 l -9 5 l -9 0 l 0 -9 l 5 -9 l -5 -9 l 0 -9 z"  style="fill:powderblue; stroke:black"/><%
                break;
            case Node.TYPE_OR:
                %><path d="M <%=aPoint.x-18%> <%=aPoint.y-12%> l 6 0 l 0 -6 l 24 0 l 0 6 l 6 0 l 0 24 l -6 0 l 0 6 l -24 0 l 0 -6 l -6 0 z"  style="fill:powderblue; stroke:black"/><%
                break;
            case Node.TYPE_DELAY:
                %><path d="M <%=aPoint.x-20%> <%=aPoint.y-13%> l 40 0 l -13 25 l -14 0 z"  style="fill:powderblue; stroke:black"/><%
                break;
            case Node.TYPE_SUB_PROCESS:
                %><path d="M <%=aPoint.x-40%> <%=aPoint.y-12%> l 16 -13 l 48 0 l 16 13 l 0 24 l -16 13 l -48 0 l -16 -13 z"  style="fill:powderblue; stroke:black"/><%
                drawTextBox(aPoint.x-30,aPoint.y-5,100,35,aNode.getSubPlanName(), out);
                break;
            case Node.TYPE_CHAINED_PROCESS:
                %><path d="M <%=aPoint.x-40%> <%=aPoint.y-12%> l 16 -13 l 48 0 l 16 13 l 0 24 l -16 13 l -48 0 l -16 -13 z"  style="fill:powderblue; stroke:black"/><%
                %><path d="M <%=aPoint.x-24%> <%=aPoint.y-15%> l 48 0 l -10 -4 l 3 4 l -3 4 l 10 -4 z"  style="fill:black; stroke:black"/><%
                drawTextBox(aPoint.x-30,aPoint.y-5,100,35,aNode.getChainedPlanName(), out);
                break;
            case Node.TYPE_REMOTE_SUB_PROCESS:
                %><path d="M <%=aPoint.x-40%> <%=aPoint.y-12%> l 16 -13 l 48 0 l 16 13 l 0 24 l -16 13 l -48 0 l -16 -13 z"  style="fill:powderblue; stroke:black"/><%
                drawTextBox(aPoint.x-30,aPoint.y-5,100,35,aNode.getName(), out);
                break;
            case Node.TYPE_VOTING_ACTIVITY:
                %><rect x="<%=aPoint.x-51%>" y="<%=aPoint.y-44%>" width="102" height="10" style="fill:powderblue; stroke:black"/><%
                // fall through here, don't break
            case Node.TYPE_ACTIVITY:
            default:
                %><rect x="<%=aPoint.x-51%>" y="<%=aPoint.y-34%>" width="102" height="68" style="fill:white; stroke:black"/><%
                drawTextBox(aPoint.x-50,aPoint.y,100,35,aNode.getName(), out);
                if (aNode.supportRole()) {
                    drawTextBox(aPoint.x-50,aPoint.y-35,100,35,aNode.getRole(), out);
                }
                break;
         }
    }
%>
</svg>

<%!
    public
    void
    getRoles(Node[] nodes, Writer out)
        throws Exception
    {
        roles = new Hashtable();
	int count = 1;
	int oneCord = 100;
        int increment = 1;
        for(int i = 0;  i < nodes.length; i++){
            Node aNode = nodes[i];
            if((aNode.getType() == Node.TYPE_ACTIVITY) || (aNode.getType() == Node.TYPE_VOTING_ACTIVITY)){
                if(roles.get(aNode.getRole()) == null){
                    Point ap = aNode.getPosition();
                    Point startPoint = new Point(0, ((oneCord*count)+increment));
                    roles.put(aNode.getRole(), startPoint);
		    count ++;
                    increment = increment + 10;
                }
            }else{
                continue;
            }
        }
    }
    
    public
    String
    goToLogin(HttpServletRequest request, String pageName)
        throws Exception
    {
        StringBuffer s1 = request.getRequestURL();
        s1.append("?");
        s1.append(request.getQueryString());

        String loginUrl = "Login.jsp?nextPage="
                      +URLEncoder.encode(s1.toString(), "UTF-8")
                      +"&nextLink="
                      +URLEncoder.encode(pageName, "UTF-8");
        return loginUrl;
    }


    public
    void
    drawLine(Point a, Point b, String style, Writer out)
        throws Exception
    {
        out.write("<line x1=\"");
        out.write(Integer.toString(a.x));
        out.write("\" y1=\"");
        out.write(Integer.toString(a.y));
        out.write("\" x2=\"");
        out.write(Integer.toString(b.x));
        out.write("\" y2=\"");
        out.write(Integer.toString(b.y));
        out.write("\" style=\"");
        out.write(style);
        out.write("\" marker-end=\"url(#Triangle)\"/>\n");
    }
    public
    void
    drawPath(String path, String style, Writer out)
        throws Exception
    {
        out.write("<path d=\"");
        out.write(path);
        out.write("\" style=\"");
        out.write(style);
        out.write("\" marker-end=\"url(#Triangle)\"/>\n");
    }
    public
    void
    drawText(int x, int y, String text, Writer out)
        throws Exception
    {
        if (text != null && text.length()>0) {
            out.write("<text x=\"");
            out.write(Integer.toString(x));
            out.write("\" y=\"");
            out.write(Integer.toString(y));
            out.write("\" text-anchor=\"middle\">");
            QuickForm.writeHtml(out, text);
            out.write("</text>\n");
        }
    }
    public
    void
    drawTextBox(int x, int y, int width, int height, String text, Writer out)
        throws Exception
    {
        if (text != null && text.length()>0) {
            out.write("<svg x=\"");
            out.write(Integer.toString(x));
            out.write("\" y=\"");
            out.write(Integer.toString(y));
            out.write("\" width=\"");
            out.write(Integer.toString(width));
            out.write("\" height=\"");
            out.write(Integer.toString(height));
            out.write("\"><text x=\"1\" y=\"12\">");
            QuickForm.writeHtml(out, text);
            out.write("</text></svg>\n");
        }
    }

    // figure out how the
    public
    Point
    calcEndPoint(Point a, Node aNode)
    {
        int nodeType = aNode.getType();
        Point bp = bias[nodeType];
        Point b = new Point(a.x+bp.x, a.y+bp.y+30);

        Point newEnd = new Point(b.x, b.y);
        // avoid divide by zero
        if (b.x == a.x) {
            if (a.y>b.y) {
                return new Point(b.x, b.y+35);
            }
            else {
                return new Point(b.x, b.y-35);
            }
        }

        float slope = ((float)(b.y-a.y))/(b.x-a.x);
        if (nodeType == Node.TYPE_START || nodeType == Node.TYPE_EXIT ||
            nodeType == Node.TYPE_DELAY || nodeType == Node.TYPE_OR ||
            nodeType == Node.TYPE_AND || nodeType == Node.TYPE_CONDITION) {
            // just a circle
            double angle = Math.atan(slope);
            if (a.x>b.x) {
                newEnd.y = b.y+(int)(32.0*Math.sin(angle));
                newEnd.x = b.x+(int)(32.0*Math.cos(angle));
            }
            else {
                newEnd.y = b.y-(int)(32.0*Math.sin(angle));
                newEnd.x = b.x-(int)(32.0*Math.cos(angle));
            }
            return newEnd;
        }

        if (slope > 36.0/53 || slope < -36.0/53) {
            // if it hits the top
            if (a.y<b.y) {
                newEnd.y = b.y-36;
                newEnd.x = b.x - (int) (36/slope);
            }
            // it hit the bottom
            else {
                newEnd.y = b.y+36;
                newEnd.x = b.x + (int) (36/slope);
            }
        }
        else {
            // hits right side
            if (a.x>b.x) {
                newEnd.x = b.x+53;
                newEnd.y = b.y + (int) (53*slope);
            }
            // it hit left side
            else {
                newEnd.x = b.x-53;
                newEnd.y = b.y - (int) (53*slope);
            }
        }
        return newEnd;
    }
    
    public
    void
    addPoint(StringBuffer b, String comm, Point p)
    {
        b.append(comm);
        b.append(" ");
        b.append(Integer.toString(p.x));
        b.append(" ");
        b.append(Integer.toString(p.y));
        b.append(" ");
    }

    static Point[] bias = null;
    static Hashtable roles = null;
    static Hashtable nodesTable = null;

%>
