package edu.uchicago.cs.java.finalproject.tronscan;

import java.awt.*;
import java.awt.event.*;

import java.awt.geom.*;
import java.awt.image.*;


import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;

import java.awt.Graphics;
import java.awt.Graphics2D;

import java.awt.Rectangle;


import javax.imageio.ImageIO;

import javax.swing.JFrame;
import javax.swing.JPanel;

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.IOException;

import java.net.URL;
import java.util.ArrayList;

import java.util.HashMap;


import javax.swing.JFileChooser;
import javax.swing.JLabel;

import javax.swing.JTextField;

import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;


import javax.swing.JButton;

import javax.swing.JTabbedPane;
import javax.swing.JCheckBox;

import javax.swing.JProgressBar;

import edu.uchicago.cs.java.finalproject.tronscan.lib.ImageSaver;
import edu.uchicago.cs.java.finalproject.tronscan.lib.SendMailUsingAuthentication;




import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

// tron-font for background found here:
// http://www.dafont.com/search.php?psize=m&q=tron

public class TronScan {

	public static final int WIDTH = 789;
	public static final int HEIGHT = 520;

	private JFrame frm;
	private JPanel panView;
	private Font fonResults = new Font("Arial", Font.BOLD, 20);


	private int nMidThresh; 
	private int nLowThresh; 
	private int nHighThresh; 

	//used to store data from the config file, including students. 
	//read the data from your config file into this hashmap
	private HashMap hmpConfig = new HashMap();

	public static final URL URLTRON = TronScan.class.getResource("./"); //get the current director of card
	
	//these are temporary - refactor this applicaiton and 
	//place at least these fields in the Exam class (only one Answer[] field)
	private Answer[] ansMasters = new Answer[100];
	private Answer[] ansStudents = new Answer[100];
	private BufferedImage bufImg;
	
	
	
	
	private BufferedImage bufTitle;
	private ArrayList<Pair> parCols;
	private ArrayList<Pair> parRows;
	private Rectangle[][] recChads;

	
	private JButton btnPopulate;
	private JButton btnGetFiles;
	private JTabbedPane tbp;
	private JPanel panConfig;
	private JButton btnBrowseDir;
	private JTextField txtDir;
	private JTextField txtMyEmail;
	private JCheckBox chkEmailStudents;
	private JCheckBox chkEmailExaminer;
	private JLabel lblStep1;
	private JLabel lblStep3;
	private JButton btnStep3;
	private JLabel lblStep2;
	private Button btnProcess;
	private JPanel panTest;
	private JButton button_5;
	private JButton btnStart;
	private JLabel lblToThisEmail;
	private JLabel lblEmailStudents;
	private JButton btnRec;
	private JButton btnDrawText;
	private JLabel lblBuffOps;
	private JLabel label;
	private JButton btnHue;
	private JProgressBar barProgress;
	private JButton btnAbort;
	private JLabel label_1;
	private JLabel label_2;
	private JCheckBox chkLog;
	private JMenuBar menuBar;
	private JMenu mnuFile;
	private JMenuItem mniExitApp;
	private JMenu mnuHelp;
	private JMenuItem mniAbout;
	private JMenuItem mniManual;
	private JButton btnJpeg;
	private JButton btnSendEmail;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {

		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					TronScan window = new TronScan();
					window.frm.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});

	}

	public TronScan() {
		initialize();
	}

	private void getFiles(String strPath) {

		File filDir = new File(strPath);

		File files[] = filDir.listFiles();
		for (File f : files) {

			if (f.getName().endsWith(".jpg")) {
				System.out.println(f);
			}

		}
	}


	private void populateColTransitions(BufferedImage bufImg) {

		final int SCN = 4; //this is the screen. 

		boolean[] bScreens = new boolean[SCN];

		int nLeft = 0, nRight = 0;
		for (int nCol = 0; nCol < bufImg.getWidth() - SCN; nCol++) {

			for (int nD = 0; nD < SCN; nD++) {

				bScreens[nD] = isDark(bufImg, nCol + nD, 2, nMidThresh);
			}

			//im at a transition in
			if (!bScreens[0] && !bScreens[1] && bScreens[2] && bScreens[3]) {

				nLeft = nCol + 2;

			}
			//at a transition out
			if (bScreens[0] && bScreens[1] && !bScreens[2] && !bScreens[3]) {

				nRight = nCol;
				parCols.add(new Pair(nLeft, nRight));
			}

		}

	}//end meth

	private void populateRowTransitions(BufferedImage bufImg) {

		final int SCN = 4; //this is the screen. 

		boolean[] bScreens = new boolean[SCN];

		int nTop = 0, nBottom = 0;
		for (int nRow = 0; nRow < bufImg.getHeight() - SCN; nRow++) {

			for (int nD = 0; nD < SCN; nD++) {

				bScreens[nD] = isDark(bufImg, 0, nRow + nD, nMidThresh);
			}

			//im at a transition in
			if (!bScreens[0] && !bScreens[1] && bScreens[2] && bScreens[3]) {

				nTop = nRow + 2;

			}
			//at a transition out
			if (bScreens[0] && bScreens[1] && !bScreens[2] && !bScreens[3]) {

				nBottom = nRow;
				parRows.add(new Pair(nTop, nBottom));

			}

		}

	}//end meth

	private void populateChads() {

		parRows = new ArrayList<Pair>();
		parCols = new ArrayList<Pair>();

		populateColTransitions(bufImg);
		populateRowTransitions(bufImg);

		recChads = new Rectangle[parRows.size()][parCols.size()];

		for (int nR = 0; nR < parRows.size(); nR++) {
			for (int nC = 0; nC < parCols.size(); nC++) {

				recChads[nR][nC] = new Rectangle(parCols.get(nC).getnA(), //x
						parRows.get(nR).getnA(), //y
						parCols.get(nC).getDiff(), //width
						parRows.get(nR).getDiff()); //height

			}

		}

	}//end populateChads

	
	
	
	
	//http://stackoverflow.com/questions/3514158/how-do-you-clone-a-bufferedimage
	private BufferedImage deepCopyBuff(BufferedImage bi) {
		ColorModel cm = bi.getColorModel();
		boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
		WritableRaster raster = bi.copyData(null);
		return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
	}

	private void populateAnswers(boolean bMaster) {

		BufferedImage bufOff = deepCopyBuff(bufImg);
		highLow(recChads,bufOff);
		unsaturateChads(recChads, bufOff);

		int[] nVals = new int[5];
		int nValInd = 0;
		int nAns = 0;


		
		//answers are 3-dimensional --  SUPER-COLS, each composed of ROW x COL	
		for (int nBigCol = 0; nBigCol < 4; nBigCol++) {
			for (int nR = 2; nR < recChads.length; nR++) {

				//22 is the origin of the answer values, 26 is the end of the first super column
				for (int nC = 22 + (5 * nBigCol); nC < 27 + (5 * nBigCol); nC++) {

					nVals[nValInd++] = findAveBrightness(recChads[nR][nC],
							bufOff);

				}
				if (bMaster)
					ansMasters[nAns++] = new Answer(nVals, true);
				else
					ansStudents[nAns++] = new Answer(nVals, false);

				nVals = new int[5];
				nValInd = 0;

			}

		}

	}//end meth

	
	
	private void setBuff(String strPath) {

		String strNewPath = strPath.replace("bin", "src");
		
		File filImg = new File(strNewPath);

		try {
			bufImg = ImageIO.read(filImg);
		} catch (IOException exp) {
			// TODO Auto-generated catch blo

			exp.printStackTrace();
		}

	}

	//overloaded to take a Buff
	private void setBuff(BufferedImage buf) {
		bufImg = buf;
	}

	private void setTitle(String strPath) {

	  String strNewPath = strPath.replace("bin", "src");
		
		File filImg = new File(strNewPath);

		try {
			bufTitle = ImageIO.read(filImg);
		} catch (IOException exp) {

			exp.printStackTrace();
		}

	}

	private void initialize() {

		frm = new JFrame();


		
		String strPathTitle	= this.getClass().getResource("./").getPath() +  "imgs/titleTron.jpg";
		String strPathView =  this.getClass().getResource("./").getPath() +  "imgs/scan2.jpg";

		
		setBuff(strPathView);
		setTitle(strPathTitle);

		frm.setTitle("TronScan -- early prototype");
		frm.setBounds(100, 100, 934, 742);
		frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frm.getContentPane().setLayout(null);

		tbp = new JTabbedPane(JTabbedPane.TOP);
		tbp.setBounds(10, 11, 906, 620);
		frm.getContentPane().add(tbp);

		//panConfig = new ConfigPanel(bufTitle);
		
		
		panConfig = new JPanel(){
		@Override
		public void paintComponent(Graphics g) {

			super.paintComponent(g);
			g.drawImage(bufTitle, 0, 0, null);

		}
	};

		panView = new JPanel() {

			@Override
			public void paintComponent(Graphics g) {

				super.paintComponent(g);
				g.drawImage(bufImg, 0, 0, null);

			}
		};

		tbp.addTab("Configuraiton", null, panConfig, null);
		panConfig.setLayout(null);

		btnBrowseDir = new JButton("browse");
		btnBrowseDir.setBackground(Color.LIGHT_GRAY);
		btnBrowseDir.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				//http://download.oracle.com/javase/tutorial/displayCode.html?code=http://download.oracle.com/javase/tutorial/uiswing/examples/components/FileChooserDemoProject/src/components/FileChooserDemo.java
				final JFileChooser fc = new JFileChooser();
				fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
				//In response to a button click:
				int returnVal = fc.showOpenDialog(panView);

			}
		});
		btnBrowseDir.setBounds(368, 329, 79, 23);
		panConfig.add(btnBrowseDir);

		txtDir = new JTextField();
		txtDir.setBounds(457, 330, 406, 20);
		panConfig.add(txtDir);
		txtDir.setColumns(10);

		txtMyEmail = new JTextField();
		txtMyEmail.setBounds(415, 403, 224, 20);
		panConfig.add(txtMyEmail);
		txtMyEmail.setColumns(10);

		chkEmailStudents = new JCheckBox("");
		chkEmailStudents.setForeground(SystemColor.activeCaptionText);
		chkEmailStudents.setBackground(Color.BLACK);
		chkEmailStudents.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {

				if (chkEmailStudents.isSelected()) {

					showStep3();
				} else {
					hideStep3();
				}

			}
		});

		chkEmailStudents.setBounds(286, 473, 21, 23);
		panConfig.add(chkEmailStudents);

		chkEmailExaminer = new JCheckBox("");
		chkEmailExaminer.setBackground(Color.BLACK);
		chkEmailExaminer.setForeground(SystemColor.activeCaptionText);
		chkEmailExaminer.setBounds(320, 403, 21, 23);
		panConfig.add(chkEmailExaminer);

		lblStep1 = new JLabel(
				"Step 1: Browse to the directory with your scanned Tron-Scan forms. ");
		lblStep1.setBackground(SystemColor.windowBorder);
		lblStep1.setForeground(Color.WHITE);
		lblStep1.setBounds(343, 288, 517, 30);
		panConfig.add(lblStep1);

		lblStep3 = new JLabel(
				"Step 3: Confirm the email addresses of your students.");
		lblStep3.setBackground(SystemColor.windowBorder);
		lblStep3.setForeground(Color.WHITE);
		lblStep3.setBounds(343, 473, 580, 30);
		panConfig.add(lblStep3);

		btnStep3 = new JButton("Edit email list");
		btnStep3.setBackground(Color.LIGHT_GRAY);
		btnStep3.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				//with a java notepad that you create especially for this app (not platform-specific notepad) 
				//open the config file and allow read/write
			}
		});
		btnStep3.setBounds(368, 514, 126, 23);
		panConfig.add(btnStep3);

		lblStep2 = new JLabel("Step 2: determine who will be emailed.");
		lblStep2.setBackground(Color.WHITE);
		lblStep2.setForeground(Color.WHITE);
		lblStep2.setBounds(338, 363, 496, 30);
		panConfig.add(lblStep2);

		lblToThisEmail = new JLabel(
				"Email each jpg report to Examiner:");
		lblToThisEmail.setForeground(Color.WHITE);
		lblToThisEmail.setBounds(74, 406, 218, 14);
		panConfig.add(lblToThisEmail);

		lblEmailStudents = new JLabel("Email Students:");
		lblEmailStudents.setForeground(Color.WHITE);
		lblEmailStudents.setBounds(158, 473, 122, 14);
		panConfig.add(lblEmailStudents);

		tbp.addTab("ViewResult (testing only)", null, panView, null);

		panTest = new JPanel();
		tbp.addTab("Buttons for testing", null, panTest, null);
		panTest.setLayout(null);

		btnPopulate = new JButton("findAnswers");
		btnPopulate.setBounds(45, 69, 132, 23);
		panTest.add(btnPopulate);

		btnGetFiles = new JButton("displayJpegsInDir");
		btnGetFiles.setBounds(45, 340, 194, 23);
		panTest.add(btnGetFiles);

		btnRec = new JButton("Print Random Rectangles");
		btnRec.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				//display some random grade-marks
				setViewTab();
				populateChads();
				paintRandomRecs();

			}
		});
		btnRec.setBounds(45, 178, 208, 23);
		panTest.add(btnRec);

		btnDrawText = new JButton("draw text on result");
		btnDrawText.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				drawStringSideways("Your score is 84%", 235, 520);
				drawStringSideways("Correct:21", 260, 520);
				drawStringSideways("Incorrect:4", 285, 520);

			}

		});
		btnDrawText.setBounds(45, 226, 195, 23);
		panTest.add(btnDrawText);

		lblBuffOps = new JLabel("BufferedImage operations");
		lblBuffOps.setBounds(45, 44, 178, 14);
		panTest.add(lblBuffOps);

		label = new JLabel("Other operations");
		label.setBounds(45, 303, 161, 14);
		panTest.add(label);

		btnHue = new JButton("hue shift to purple");
		btnHue.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				bufImg = hueColor(bufImg, 0.7f);
				panView.repaint();
				setViewTab();

			}
		});
		btnHue.setBounds(45, 120, 178, 23);
		panTest.add(btnHue);
		
		btnJpeg = new JButton("save jpg");
		btnJpeg.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
		
				String strName = "myImage";
				//you may need to right-click your project  and select refresh to see the result
				if (ImageSaver.save(bufImg, System.getProperty("user.dir") + "/", strName))
					JOptionPane.showMessageDialog(null, "success...image saved as " + strName + ".jpg. you may need to right-click your project  and select refresh to see the result");
				else
					JOptionPane.showMessageDialog(null, "failed. image " + strName + ".jpg not saved!");
				
				
			}
		});
		btnJpeg.setBounds(45, 388, 117, 24);
		panTest.add(btnJpeg);
		
		btnSendEmail = new JButton("Send email");
		btnSendEmail.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				
				//you should use the many-args version, not the no-args version
				if (SendMailUsingAuthentication.sendEmail())
					JOptionPane.showMessageDialog(null, "success. email with attachment sent");
				else
					JOptionPane.showMessageDialog(null, "failed. email NOT sent");
			}
		});
		btnSendEmail.setBounds(45, 437, 117, 24);
		panTest.add(btnSendEmail);

		btnStart = new JButton("Start");
		btnStart.setFont(new Font("Tahoma", Font.PLAIN, 27));
		btnStart.setBackground(new Color(0, 128, 128));
		btnStart.setBounds(768, 642, 148, 48);
		frm.getContentPane().add(btnStart);

		button_5 = new JButton("New button");
		button_5.setBounds(749, 656, 167, 84);
		btnGetFiles.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

		
				String strPath	= this.getClass().getResource("./").getPath() +  "imgs/";
				getFiles(strPath);

		
			}
		});
		btnPopulate.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				
				setViewTab();

				populateChads();
				populateAnswers(false);
				iterateAnswers(false);

			}

		});

		btnProcess = new Button("Start");
		btnProcess.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				tbp.setSelectedIndex(1);

			}
		});
		btnProcess.setBounds(710, 652, 206, 57);

		label_1 = new JLabel(
				"Email activity log and spreadsheet to Examiner:");
		label_1.setForeground(Color.WHITE);
		label_1.setBounds(17, 431, 297, 14);
		panConfig.add(label_1);

		label_2 = new JLabel("Examiner's email address");
		label_2.setForeground(Color.WHITE);
		label_2.setBounds(650, 406, 173, 14);
		panConfig.add(label_2);

		chkLog = new JCheckBox("");
		chkLog.setForeground(Color.WHITE);
		chkLog.setBackground(Color.BLACK);
		chkLog.setBounds(320, 431, 21, 23);
		panConfig.add(chkLog);

		barProgress = new JProgressBar();
		barProgress.setBounds(20, 642, 558, 48);
		frm.getContentPane().add(barProgress);

		btnAbort = new JButton("Abort");
		btnAbort.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
			}
		});
		btnAbort.setFont(new Font("Tahoma", Font.PLAIN, 27));
		btnAbort.setBackground(new Color(153, 0, 51));
		btnAbort.setBounds(599, 642, 148, 48);
		frm.getContentPane().add(btnAbort);

		menuBar = new JMenuBar();
		frm.setJMenuBar(menuBar);

		mnuFile = new JMenu("File");
		menuBar.add(mnuFile);

		mniExitApp = new JMenuItem("Exit");
		mnuFile.add(mniExitApp);

		mnuHelp = new JMenu("Help");
		menuBar.add(mnuHelp);

		mniManual = new JMenuItem("Manual");
		mnuHelp.add(mniManual);

		mniAbout = new JMenuItem("About");
		mnuHelp.add(mniAbout);

		barProgress = new JProgressBar(0, 100);
		barProgress.setValue(0);
		barProgress.setStringPainted(true);

		hideStep3();
		
		nMidThresh = findAveBrightness(bufImg);

	}

	//http://greybeardedgeek.net/2009/05/15/rotated-text-in-java-swing-2d/
	private void drawStringSideways(String str, int nX, int nY) {
		// Create a rotation transformation for the font.
		AffineTransform fontAT = new AffineTransform();

		Graphics2D grp = (Graphics2D) bufImg.getGraphics();

		Composite original = grp.getComposite();
		//Set to semi translucent
		Composite translucent = AlphaComposite.getInstance(
				AlphaComposite.SRC_OVER, 0.30f);
		grp.setComposite(translucent);

		grp.setColor(Color.RED);
		grp.setFont(fonResults);

		Font theFont = grp.getFont();
		// Derive a new font using a rotatation transform
		fontAT.rotate(Math.toRadians(-90));
		Font theDerivedFont = theFont.deriveFont(fontAT);

		// set the derived font in the Graphics2D context
		grp.setFont(theDerivedFont);

		grp.drawString(str, nX, nY);
		panView.repaint();
		setViewTab();

		//Set back to original
		grp.setComposite(original);

		grp.setFont(theFont);
	}

	private void paintRandomRecs() {

		int nPrint;
		Color col;
		for (int nR = 0; nR < recChads.length; nR++) {
			for (int nC = 0; nC < recChads[0].length; nC++) {

				nPrint = (int) (Math.random() * 100);
				if (nPrint < 40) {

					if (nPrint < 10)
						col = Color.RED;
					else
						col = Color.CYAN;

					drawRect(bufImg, recChads[nR][nC], col);

				}

			}
		}

	}

	private void showStep3() {

		lblStep3.setVisible(true);
		btnStep3.setVisible(true);

	}

	private void hideStep3() {
		lblStep3.setVisible(false);
		btnStep3.setVisible(false);
	}

	private void setViewTab() {
		tbp.setSelectedIndex(1);
	}

	private void drawRect(BufferedImage buf, Rectangle rec, Color col) {

		//http://stackoverflow.com/questions/2642577/transparency-in-bufferedimage-objects
		Graphics2D g2d = (Graphics2D) buf.getGraphics(); //Some graphics object
		Composite original = g2d.getComposite();
		Composite translucent = AlphaComposite.getInstance(
				AlphaComposite.SRC_OVER, 0.25f);
		g2d.setComposite(translucent);
		g2d.setColor(col);
		g2d.fillRect(rec.x, rec.y, rec.width, rec.height);

		g2d.setComposite(original);

	}

	//for testing only
	private void iterateAnswers(boolean bMaster) {
		int nC = 1;

		if (bMaster) {

			for (Answer ans : ansMasters) {
				System.out.print(nC++);
				System.out.println(ans);

			}
		} else {

			for (Answer ans : ansStudents) {
				System.out.print(nC++);
				System.out.println(ans);

			}
		}

	}

	private int rgbValue(int nR, int nG, int nB) {
		int nA = 0xff << 24;
		nG = (nG & 0xff) << 8;
		nR = (nR & 0xff) << 16;
		nB = (nB & 0xff);

		return nA | nR | nG | nB;
	}

	//hue color
	//fHue is a number betwwn 0 and 1 that when multiplied by 360 gives you degrees on this wheel: 
	//http://www.procato.com/color+wheel/?hue=15 
	//so .7 will give you violet. This is good because we use red and cyan for wrong and right answers later. 
	private BufferedImage hueColor(BufferedImage bufParam, float fHue) {
		BufferedImage bufRet = new BufferedImage(bufParam.getWidth(),
				bufParam.getHeight(), BufferedImage.TYPE_INT_RGB);
		int nRed, nGreen, nBlue, nClr;
		float[] fHSBs;
		int nNew;

		for (int nX = 0; nX < bufParam.getWidth(); nX++) {
			for (int nY = 0; nY < bufParam.getHeight(); nY++) {

				//bit mask
				nClr = bufParam.getRGB(nX, nY);
				nRed = (nClr & 0x00ff0000) >> 16;
				nGreen = (nClr & 0x0000ff00) >> 8;
				nBlue = nClr & 0x000000ff;

				fHSBs = Color.RGBtoHSB(nRed, nGreen, nBlue, null);
				nNew = Color.HSBtoRGB(fHue, fHSBs[1], fHSBs[2]);

				nRed = (nNew & 0x00ff0000) >> 16;
				nGreen = (nNew & 0x0000ff00) >> 8;
				nBlue = nNew & 0x000000ff;

				bufRet.setRGB(nX, nY, rgbValue(nRed, nGreen, nBlue));

			}
		}

		return bufRet;

	}

	//clear saturation in chads 
	private void unsaturateChads(Rectangle[][] recChs, BufferedImage bufParam) {
		//BufferedImage bufRet = new BufferedImage(bufParam.getWidth(), bufParam.getHeight(), BufferedImage.TYPE_INT_RGB);
		int nRed, nGreen, nBlue, nClr;
		//Color col;
		float[] hsb;

		for (int nR = 0; nR < recChs.length; nR++) {
			for (int nC = 0; nC < recChs[0].length; nC++) {

				for (int nX = recChs[nR][nC].x; nX < recChs[nR][nC].x
						+ recChs[nR][nC].width; nX++) {
					for (int nY = recChs[nR][nC].y; nY < recChs[nR][nC].y
							+ recChs[nR][nC].height; nY++) {

						//use bit mask
						nClr = bufParam.getRGB(nX, nY);
						nRed = (nClr & 0x00ff0000) >> 16;
						nGreen = (nClr & 0x0000ff00) >> 8;
						nBlue = nClr & 0x000000ff;

						//get hue, saturation, and brightness
						hsb = Color.RGBtoHSB(nRed, nGreen, nBlue, null);

						//set the saturation to zero (strip out any color)
						int nNew = Color.HSBtoRGB(hsb[0], 0, hsb[2]);

						//get the rbg values of this new grey color, re-use the same variables 
						nRed = (nNew & 0x00ff0000) >> 16;
						nGreen = (nNew & 0x0000ff00) >> 8;
						nBlue = nNew & 0x000000ff;

						//in our new bufferred image, write a pixel 
						bufParam.setRGB(nX, nY, rgbValue(nRed, nGreen, nBlue));

					}
				}
			}

		}

	}

	private boolean isDark(BufferedImage bufP, int nX, int nY, int nThresh) {
		int nClr = bufP.getRGB(nX, nY);

		int nG = (int) (((nClr & 0x00ff0000) >> 16) * 0.2989
				+ (nClr & 0x000000ff) * 0.5870 + ((nClr & 0x0000ff00) >> 8) * 0.1140);

		
		if (nG < nThresh) {
			return true;
		} else {
			return false;
		}

	}


	private int findAveBrightness(Rectangle rec, BufferedImage bufParam) {

		int nGreyValue = 0;

		int nRed, nGreen, nBlue, nClr;

		int nCount = 0;
		int nBright = 0;

		for (int nX = rec.x; nX < rec.x + rec.width; nX++) {
			for (int nY = rec.y; nY < rec.y + rec.height; nY++) {

				//bit mask
				nClr = bufParam.getRGB(nX, nY);
				nRed = (nClr & 0x00ff0000) >> 16;
				nGreen = (nClr & 0x0000ff00) >> 8;
				nBlue = nClr & 0x000000ff;

				//convert 24bit RGB color to 8bit grey value
				nGreyValue = (int) ((nRed * 0.2989) + (nGreen * 0.5870) + (nBlue * 0.1140));

				nBright += nGreyValue;
				nCount++;

			}
		}

		return nBright / nCount;

	}





//overloaded to determine nMidThreshold
	private int findAveBrightness(BufferedImage bufParam) {

		int nGreyValue = 0;

		int nRed, nGreen, nBlue, nClr;

		int nCount = 0;
		int nBright = 0;

		for (int nX = 0; nX < bufParam.getWidth(); nX++) {
			for (int nY = 0; nY < bufParam.getHeight(); nY++) {

				//bit mask
				nClr = bufParam.getRGB(nX, nY);
				nRed = (nClr & 0x00ff0000) >> 16;
				nGreen = (nClr & 0x0000ff00) >> 8;
				nBlue = nClr & 0x000000ff;

				//convert 24bit RGB color to 8bit grey value
				nGreyValue = (int) ((nRed * 0.2989) + (nGreen * 0.5870) + (nBlue * 0.1140));

				nBright += nGreyValue;
				nCount++;

			}
		}

		return (nBright / nCount) - 30; //adjust

	}

	
	
	
	
	   //method used to determine the average darkness of the chads on a form
		private void highLow(Rectangle[][] recChs, BufferedImage bufParam) {
			//BufferedImage bufRet = new BufferedImage(bufParam.getWidth(), bufParam.getHeight(), BufferedImage.TYPE_INT_RGB);
			int nRed, nGreen, nBlue, nClr;
			//Color col;
			float[] hsb;
			
			int nGreyValue = 0;
			int nValC=0;
			
			int[] nVals = new int[recChs.length * recChs[0].length];


			int nCount = 0;
			int nBright = 0;

			for (int nR = 0; nR < recChs.length; nR++) {
				for (int nC = 0; nC < recChs[0].length; nC++) {

					for (int nX = recChs[nR][nC].x; nX < recChs[nR][nC].x
							+ recChs[nR][nC].width; nX++) {
						for (int nY = recChs[nR][nC].y; nY < recChs[nR][nC].y
								+ recChs[nR][nC].height; nY++) {

							//bit mask
							nClr = bufParam.getRGB(nX, nY);
							nRed = (nClr & 0x00ff0000) >> 16;
							nGreen = (nClr & 0x0000ff00) >> 8;
							nBlue = nClr & 0x000000ff;

							//convert 24bit RGB color to 8bit grey value
							nGreyValue = (int) ((nRed * 0.2989) + (nGreen * 0.5870) + (nBlue * 0.1140));

							nBright += nGreyValue;
							nCount++;

						}
					}
					
					nVals[nValC++] = nBright/ nCount;
					nCount = 0;
					nBright = 0;
					
				}

			}//done iter
			
			int nLow = nVals[0];
			for (int nC = 1; nC < nVals.length; nC++) {
				if(nVals[nC] < nLow )
					nLow = nVals[nC];
				
			}
			
			int nHigh = nVals[0];
			for (int nC = 1; nC < nVals.length; nC++) {
				if(nVals[nC] > nHigh )
					nHigh = nVals[nC];
				
			}
			
			
			int nQuart = (int)((nHigh - nLow) * 0.25);
			nLowThresh = nLow + nQuart ;//lower third
			nHighThresh = nHigh -nQuart;//highest third
			
			

		}
}//end class





