package wprover;

import java.awt.*;
import java.util.*;

import javax.swing.*;
import javax.swing.Timer;

/**
 * Created by IntelliJ IDEA.
 * User: Ye
 * Date: 2006-4-5
 * Time: 13:33:53
 * To change this template use File | Settings | File Templates.
 */

public abstract class JFlash {

    protected Timer timer;
    protected JPanel panel;
    protected int n = 8;
    protected static double ZERO = 1.0;
    final static float[] DF = {8.0f};
    final static float[] DF1 = {2.0f};
    final static BasicStroke BStroke = new BasicStroke(1.0f);
    final static BasicStroke BStroke2 = new BasicStroke(3.0f);
    final public static BasicStroke Dash = new BasicStroke(2.0f,
            BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 5.0f, DF, 0.0f);

    final public static BasicStroke DASH1 = new BasicStroke(1.0f,
            BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 5.0f, DF, 0.0f);
    final static int RAD = 40;
    final static int MAX = 100;
    final static int MIN_STEP = 20;

    final static double ASTEP = 0.120; // angle step


    //protected static Vector linelist = new Vector();
    protected Color color = Color.red;
    protected boolean finished = false;
    protected boolean vType = false;
    protected boolean fb = false;
    protected int TIME_INTERVAL = CMisc.getFlashInterval();


    public void updateTimer() {
        if (timer != null)
            timer.setDelay(CMisc.getFlashInterval());
    }

    public void setFlashFb(boolean f) {
        fb = f;
    }

    public void setDealy(int n) {
        if (timer != null)
            timer.setDelay(n);
    }

    public boolean getFlashFb() {
        return fb;
    }

    public JFlash(JPanel p) {
        panel = p;
    }

    public void setvisibleType(boolean t) {
        vType = t;
    }

    public boolean getvisibleType() {
        return vType;
    }

    public void setColor(Color c) {
        color = c;
    }

    public Color getColor() {
        return color;
    }

    public abstract boolean draw(Graphics2D g2);

    public void recalculate() {
    }

    public void createTimer(int n) {
    }

    public void start() {
        if (timer != null) {
            finished = false;
            timer.start();
            n = 8;
        }
    }

    public void stop() {
        if (timer != null) {
            timer.stop();
            finished = true;
        }
    }

    public boolean isfinished() {
        return this.finished;
    }

    public boolean isrRunning() {
        return timer.isRunning();
    }

    final public void setDrawDash(Graphics2D g2) {
        g2.setColor(Color.red);
        g2.setStroke(DASH1);
    }

    final public void setDrawDashFb(Graphics2D g2) {
        if (fb) {
            g2.setStroke(BStroke);
        } else {
            g2.setStroke(Dash);
        }
        g2.setColor(Color.red);
    }

    final public void setDrawDashFb2(Graphics2D g2) {
        if (fb) {
            g2.setStroke(BStroke2);
        } else {
            g2.setStroke(Dash);
        }
        g2.setColor(Color.red);
    }

    final public boolean isZero(double d) {
        return Math.abs(d) < ZERO;
    }

    final static double[] interect_LL(double x1, double y1, double x2,
                                      double y2, double x3, double y3,
                                      double x4, double y4) {

        double result[] = new double[2];
        if (Math.abs(x1 - x2) < ZERO) {
            if (Math.abs(x3 - x4) < ZERO) {
                return null;
            }
            double k = (y3 - y4) / (x3 - x4);
            result[0] = x1;
            result[1] = k * (x1 - x3) + y3;
            return result;
        }
        if (Math.abs(x3 - x4) < ZERO) {
            double k0 = (y1 - y2) / (x1 - x2);
            result[0] = x3;
            result[1] = k0 * (x3 - x1) + y1;
            return result;
        }
        double k0 = (y1 - y2) / (x1 - x2);
        double k1 = (y3 - y4) / (x3 - x4);

        double x = (y3 - y1 + k0 * x1 - k1 * x3) / (k0 - k1);
        double y = k0 * (x - x1) + y1;

        result[0] = x;
        result[1] = y;
        return result;
    }

    final public static void drawAngle(double x1, double y1, double x2, double y2,
                                       double x3, double y3, double x4, double y4,
                                       int rad, Graphics2D g2) {
        double r[] = interect_LL(x1, y1, x2, y2, x3, y3, x4, y4);
        if (r == null) {
            return;
        }
        if (Math.abs(r[0]) > 10000 || Math.abs(r[1]) > 10000) {
            return;
        }
        int radius = rad;
        double psx, psy;
        double pex, pey;
        psx = psy = pex = pey = 0;
        if (spt(x1, y1, r[0], r[1])) {
            psx = x2;
            psy = y2;

        } else {
            psx = x1;
            psy = y1;
        }

        if (spt(x3, y3, r[0], r[1])) {
            pex = x4;
            pey = y4;

        } else {
            pex = x3;
            pey = y3;
        }

        double dx1 = psx - r[0];
        double dy1 = psy - r[1];
        dy1 = (-1) * dy1;

        double k1 = dy1 / dx1;
        double r1 = Math.atan(k1);
        if (dx1 < 0) {
            r1 += Math.PI;
        }

        double t = Math.sqrt(dx1 * dx1 + dy1 * dy1);
        dx1 = dx1 / t;
        dy1 = dy1 / t;

        double dx2 = pex - r[0];
        double dy2 = pey - r[1];

        dy2 = (-1) * dy2;
        double k2 = dy2 / dx2;
        double r2 = Math.atan(k2);

        if (dx2 < 0) {
            r2 += Math.PI;
        }

        t = Math.sqrt(dx2 * dx2 + dy2 * dy2);
        dx2 = dx2 / t;
        dy2 = dy2 / t;

        double jx = dx2 * radius + r[0];
        double jy = (-1) * dy2 * radius + r[1];

        int ri1 = (int) (180 * r1 / Math.PI);
        double dr = (180 * (r2 - r1) / Math.PI);
        double tr = dr;


        if (dr > 180) {
            dr = dr - 360;
        } else if (dr < -180) {
            dr = dr + 360;
        }


        double rc = dr * Math.PI / (360);
        double cx = (dx1 * Math.cos(rc) - dy1 * Math.sin(rc)) * (radius + 6) + r[0];
        double cy = -(dy1 * Math.cos(rc) + dx1 * Math.sin(rc)) * (radius + 6) + r[1];


        double dr1 = dr;
        double k = dr1;
        k = Math.abs(k);

        if (CMisc.ANGLE_TYPE == 1) {

            double lr = 12.0;

            double alpha = -Math.PI / 3;
            if (dr > 0) {
                alpha = -alpha;
                dr = (dr - 180 * Math.cos(Math.PI / 2.0 - alpha) * lr * 1 /
                        (3 * Math.PI * radius));
                if (dr < 0) {
                    dr = 0;
                }
            } else {
                dr = (dr + 180 * Math.cos(Math.PI / 2.0 + alpha) * lr * 1 /
                        (3 * Math.PI * radius));
                if (dr > 0) {
                    dr = 0;
                }
            }
            dy2 = -dy2;

            double c1 = Math.cos(alpha);
            double s1 = Math.sin(alpha);
            double c2 = Math.cos(Math.PI - alpha);
            double s2 = Math.sin(Math.PI - alpha);

            double jx1 = (dx2 * c1 - dy2 * s1) * lr + jx;
            double jy1 = (dy2 * c1 + dx2 * s1) * lr + jy;
            double jx2 = (dx2 * c2 - dy2 * s2) * lr + jx;
            double jy2 = (dy2 * c2 + dx2 * s2) * lr + jy;

            if (dr >= 0) {
                dr += 1.5;
            } else {
                dr -= 1.5;
            }

            int[] xp = new int[4];
            int[] yp = new int[4];
            xp[0] = (int) jx;
            xp[1] = (int) jx1;
            xp[2] = (int) (jx1 / 3 + jx2 / 3 + jx / 3);
            xp[3] = (int) jx2;
            yp[0] = (int) jy;
            yp[1] = (int) jy1;
            yp[2] = (int) (jy1 / 3 + jy2 / 3 + jy / 3);
            yp[3] = (int) jy2;
            g2.fillPolygon(xp, yp, 4);
        }

        g2.drawArc((int) r[0] - radius, (int) r[1] - radius, radius * 2, radius * 2, ri1, (int) dr);
        g2.setColor(Color.black);
        g2.setFont(CMisc.font);
        if (CMisc.show_angle_text) {
            if (k > 0) {
                k = k * 100 + 50;
            } else {
                k = k * 100 - 50;
            }
            g2.drawString(new Float((int) ((k) / 100)).toString(), (int) cx, (int) cy);
        }

    }

    public static void drawAngle(CPoint p1, CPoint p2, CPoint p3, CPoint p4,
                                 int rad, Graphics2D g2) {
        if (p1 != null && p2 != null && p3 != null && p4 != null) {
            drawAngle(p1.getx(), p1.gety(), p2.getx(), p2.gety(), p3.getx(),
                    p3.gety(), p4.getx(), p4.gety(), rad, g2);
        }
    }

    static boolean spt(double x0, double y0, double x, double y) {
        return Math.pow(x0 - x, 2) + Math.pow(y0 - y, 2) <
                CMisc.ZERO * CMisc.ZERO;
    }

    static public void drawALine3Short(CPoint p1, CPoint p2, double x, double y,
                                       Graphics2D g2) {

        if ((x - p1.getx()) * (x - p2.getx()) < 0 ||
                (y - p1.gety()) * (y - p2.gety()) < 0) {
            return;
        }

        if (Math.pow(p1.getx() - x, 2) + Math.pow(p1.gety() - y, 2) <
                Math.pow(p2.getx() - x, 2) + Math.pow(p2.gety() - y, 2)) {
            g2.drawLine((int) p1.getx(), (int) p1.gety(), (int) x, (int) y);
        } else {
            g2.drawLine((int) p2.getx(), (int) p2.gety(), (int) x, (int) y);
        }

    }

    static public void drawALine3(CPoint p1, CPoint p2, double x, double y,
                                  boolean ln, Graphics2D g2) {
        if (Math.abs(x) > 10000 || Math.abs(y) > 10000) {
            return;
        }

        if (p1.getx() > p2.getx()) {
            CPoint p = p1;
            p1 = p2;
            p2 = p;
        }
        double x1, y1, x2, y2;
        x1 = p1.getx();
        y1 = p1.gety();
        x2 = p2.getx();
        y2 = p2.gety();
        if (x < x1) {
            g2.drawLine((int) x, (int) y, (int) x2, (int) y2);
        } else if (x > x1 && x < x2) {
            if (ln) {
                g2.drawLine((int) x1, (int) y1, (int) x2, (int) y2);
            }
        } else if (x > x2) {
            g2.drawLine((int) x, (int) y, (int) x1, (int) y1);
        } else { // ==
            if (p1.gety() > p2.gety()) {
                CPoint p = p1;
                p1 = p2;
                p2 = p;
            }
            x1 = p1.getx();
            y1 = p1.gety();
            x2 = p2.getx();
            y2 = p2.gety();
            if (y < y1) {
                g2.drawLine((int) x, (int) y, (int) x2, (int) y2);
            } else if (y > y1 && y < y2) {
                g2.drawLine((int) x1, (int) y1, (int) x2, (int) y2);
            } else if (y > y2) {
                g2.drawLine((int) x, (int) y, (int) x1, (int) y1);
            } else {
                if (ln) {
                    g2.drawLine((int) x1, (int) y1, (int) x2, (int) y2);
                }
            }
        }
    }

    static double getcircleDr(double x1, double y1) {
        double k = y1 / x1;
        double r = Math.atan(k);
        if (x1 < 0) {
            r += Math.PI;
        }
        return r;
    }

    protected static Color getRatioColor(int c1, int c2, double ra) {
        Color o1 = drawData.getColor(c1);
        Color o2 = drawData.getColor(c2);
        double r1 = ra;
        double r2 = 1 - ra;

        int r = (int) (o1.getRed() * r2 + o2.getRed() * r1);
        int g = (int) (o1.getGreen() * r2 + o2.getGreen() * r1);
        int b = (int) (o1.getBlue() * r2 + o2.getBlue() * r1);
        Color c = new Color(r, g, b);
        return c;
    }

}
