package com.sso.utils;

import com.google.code.kaptcha.NoiseProducer;
import com.google.code.kaptcha.util.Configurable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;

/**
 * @author hongawen
 * @Date: 2019/5/14 10:08
 */
public class ComplexNoise extends Configurable implements NoiseProducer {
    private static final Logger logger = LoggerFactory.getLogger(ComplexNoise.class);
    @Override
    public void makeNoise(BufferedImage image, float factorOne, float factorTwo, float factorThree, float factorFour) {
        Color color = getConfig().getNoiseColor();
        // image size
        int width = image.getWidth();
        int height = image.getHeight();
        // the points where the line changes the stroke and direction
        Point2D[] pts = null;
        Point2D[] pts1 = null;
        SecureRandom rand= null;
        try {
            rand = SecureRandom.getInstance("SHA1PRNG");
            CubicCurve2D cc = new CubicCurve2D.Float(width * factorOne, height
                    * rand.nextFloat(), width * factorTwo, height
                    * rand.nextFloat(), width * factorThree, height
                    * rand.nextFloat(), width * factorFour, height
                    * rand.nextFloat());
            CubicCurve2D cc1 = new CubicCurve2D.Float(width * factorOne, height
                    * rand.nextFloat(), width * factorTwo, height
                    * rand.nextFloat(), width * factorThree, height
                    * rand.nextFloat(), width * factorFour, height
                    * rand.nextFloat());
            // creates an iterator to define the boundary of the flattened curve
            PathIterator pi = cc.getPathIterator(null, 2);
            PathIterator pi1 = cc1.getPathIterator(null, 2);
            Point2D tmp[] = new Point2D[200];
            Point2D tmp1[] = new Point2D[200];
            int i = 0;
            // while pi is iterating the curve, adds points to tmp array
            while (!pi.isDone())
            {
                float[] coords = new float[6];
                switch (pi.currentSegment(coords))
                {
                    case PathIterator.SEG_MOVETO:
                    case PathIterator.SEG_LINETO:
                        tmp[i] = new Point2D.Float(coords[0], coords[1]);
                }
                pi.next();
                i++;
            }

            int j=0;
            while (!pi1.isDone())
            {
                float[] coords1 = new float[6];
                switch (pi1.currentSegment(coords1))
                {
                    case PathIterator.SEG_MOVETO:
                    case PathIterator.SEG_LINETO:
                        tmp1[j] = new Point2D.Float(coords1[0], coords1[1]);
                }
                pi1.next();
                j++;
            }

            pts = new Point2D[i];
            pts1 = new Point2D[j];
            System.arraycopy(tmp, 0, pts, 0, i);
            System.arraycopy(tmp1, 0, pts1, 0, j);

            Graphics2D graph = (Graphics2D) image.getGraphics();
            graph.setRenderingHints(new RenderingHints(
                    RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON));

            graph.setColor(color);

            // for the maximum 3 point change the stroke and direction
            for (i = 0; i < pts.length - 1; i++)
            {
                if (i < 3)
                    graph.setStroke(new BasicStroke(0.9f * (4 - i)));
                graph.drawLine((int) pts[i].getX(), (int) pts[i].getY(),
                        (int) pts[i + 1].getX(), (int) pts[i + 1].getY());
            }

            for (i = 0; i < pts1.length - 1; i++)
            {
                if (i < 3)
                    graph.setStroke(new BasicStroke(0.9f * (4 - i)));
                graph.drawLine((int) pts1[i].getX(), (int) pts1[i].getY(),
                        (int) pts1[i + 1].getX(), (int) pts1[i + 1].getY());
            }
            graph.dispose();
        } catch (NoSuchAlgorithmException e) {
           logger.error("操作发生异常，异常是"+e.getMessage());
        }


    }
}
