package page.image;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import org.wikiwebserver.core.WareHouse;
import org.wikiwebserver.core.WikiMap;
import org.wikiwebserver.handler.http.FormData;
import org.wikiwebserver.handler.http.HTTPHandler;
import org.wikiwebserver.handler.http.interfaces.HTTPResponder;

public class CAPTCHAImage implements HTTPResponder {
    
    private static final int captchaLength = 6;
	
    public Object respond(HTTPHandler conn) throws IOException {

        int size = 50;
        
        StringBuilder builder = new StringBuilder();
        for (int i=0; i<captchaLength; i++) {
            int r = rand.nextInt(2);
            if (r == 0) {
                builder.append((char) ('a' + rand.nextInt(26)));
            } else if (r == 1) {
                builder.append((char) ('0' + rand.nextInt(10)));
            }
            if (i % 3 == 2) {
                builder.append(' ');
            }
        }
        String captcha = builder.toString();        
        
        // Obtain requested counter properties
        FormData formData = conn.getRequest().getFormData();
        if (formData != null) {
            String sizeString = formData.getFirst("size");        
            if (sizeString != null) size = Integer.parseInt(sizeString);
        }
        if (size < 1 || size > 100) size = 50;        
        
        // Generate font and text to display
        Font font = new Font("SansSerif", Font.PLAIN, size);
        
        // Figure out the size required to draw text
        Graphics2D g2d = new BufferedImage(1,1,BufferedImage.TYPE_INT_RGB).createGraphics();
        
        // Can cause problems in Windows with custom security model
        FontMetrics fm = g2d.getFontMetrics(font);
        int width = fm.stringWidth(captcha);
        int height = fm.getHeight();
        int ascent = fm.getAscent();
        
        // Render the text onto an image
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        g2d = image.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                             RenderingHints.VALUE_ANTIALIAS_ON);        
        g2d.setColor(Color.white);
        g2d.fillRect(0, 0, width, height);
        g2d.setColor(Color.black);
        g2d.setFont(font);
        g2d.drawString(captcha, 0, ascent);
        
        for (int y=0; y<height; y++) {
            g2d.setColor(Color.white);
            if (rand.nextInt(10) == 0) {
                g2d.drawLine(0, y, width, y);
            }
            g2d.setColor(Color.black);
            if (rand.nextInt(15) == 0) {
                g2d.drawLine(0, y, width, y);
            }            
        }
        
        for (int x=0; x<width; x++) {
            g2d.setColor(Color.white);
            if (rand.nextInt(10) == 0) {
                g2d.drawLine(x, 0, x, height);
            }
            g2d.setColor(Color.black);
            if (rand.nextInt(15) == 0) {
                g2d.drawLine(x, 0, x, height);
            }            
        }   
        
        // Store the captcha data
        captcha = captcha.replace(" ", ""); // ignore captcha
        String browserID = conn.getRequest().getHeaders().getRequestCookies().get("browserID");
        getData().put(browserID, captcha);          
      
        return image;
    }
    
    public static boolean isCorrectCaptcha(String captcha, HTTPHandler conn) {
        if (captcha == null) return false;
        
        captcha = captcha.replace(" ", ""); // ignore spaces
        String browserID = conn.getRequest().getHeaders().getRequestCookies().get("browserID");
        if (browserID == null) {
            throw new SecurityException("Browser ID not found in cookie. Are cookies enabled?");
        }
        String correctCaptcha = (String) getData().get(browserID);
        return captcha.equals(correctCaptcha);
    }
    
    public static WikiMap getData() {
        WikiMap map = WareHouse.getWikiMap("Captchas");
        if (map == null) map = WareHouse.initWikiMap("Captchas");
        return map;        
    }    
    
    private static Random rand = new Random();    
}
