package com.ssm.util.sms.excel.parser;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.ssm.util.sms.excel.exception.ExcelParseException;
import com.ssm.util.sms.excel.exception.ValidationException;
import com.ssm.util.sms.excel.validation.rule.ValidationRule;

import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;

public class ExcelParserImpl implements ExcelParser {
	public static int CONTINUE_ON_VALIDATION = 0;

	public static int STOP_ON_ROW_VALIDATION = 1;

	public static int STOP_ON_VALIDATION = 2;
	private File excelFile;
	protected Workbook workbook;
	protected Sheet sheet;
	private int row;
	private int column;
	private int buildModel = CONTINUE_ON_VALIDATION;
	private StringBuffer buildMessage;
	private String messageEndFix = "<BR>";
	private int buildPercent;
	private Progress progress;

	public ExcelParserImpl(File excelFile) {
		this.excelFile = excelFile;

		this.row = -1;
		this.column = -1;
	}

	public void parse() throws ExcelParseException {
		parse(0);
	}

	public void parse(int index) throws ExcelParseException {
		try {
			this.workbook = Workbook.getWorkbook(this.excelFile);
		} catch (BiffException e) {
			throw new ExcelParseException("解析文件出错！");
		} catch (IOException e) {
			throw new ExcelParseException("读取文件出错");
		}
		try {
			this.sheet = this.workbook.getSheet(index);
		} catch (IndexOutOfBoundsException e) {
			throw new ExcelParseException("获取工作簿越界！");
		}
		this.row = this.sheet.getRows();
		this.column = this.sheet.getColumns();
	}

	public int getRow() {
		return this.row;
	}

	public int getColumn() {
		return this.column;
	}

	public List<String> getRowValue(int row) throws ExcelParseException {
		if ((this.sheet == null) || (row < 0) || (row >= getRow())) {
			return null;
		}
		List rowValue = new ArrayList();
		for (int c = 0; c < getColumn(); c++) {
			rowValue.add(this.sheet.getCell(c, row).getContents().toString()
					.trim());
		}
		return rowValue;
	}

	public List<String> getColumnValue(int column) throws ExcelParseException {
		if ((this.sheet == null) || (column < 0) || (column >= getColumn())) {
			return null;
		}
		List columnValue = new ArrayList();
		for (int r = 0; r < getRow(); r++) {
			columnValue.add(this.sheet.getCell(column, r).getContents()
					.toString().trim());
		}
		return columnValue;
	}

	public int getBuildModel() {
		return this.buildModel;
	}

	public void setBuildModel(int buildModel) {
		this.buildModel = buildModel;
	}

	public String getMessageEndFix() {
		return this.messageEndFix;
	}

	public void setMessageEndFix(String messageEndFix) {
		this.messageEndFix = messageEndFix;
	}

	private void setBuildPercent(int buildPercent) {
		this.buildPercent = buildPercent;
		if (this.progress != null)
			this.progress.progress(buildPercent);
	}

	public int getBuildPercent() {
		return this.buildPercent;
	}

	public void setProgress(Progress progress) {
		this.progress = progress;
	}

	public List<List<String>> build(ValidationRule... validationRule)
			throws ExcelParseException, ValidationException {
		return build(1, -1, validationRule);
	}

	public List<List<String>> build(int startIndex, int endIndex,
			ValidationRule[] validationRule) throws ExcelParseException,
			ValidationException {
		if (getRow() <= 0) {
			throw new ExcelParseException("表格数据为空！");
		}

		if ((startIndex < 0) || ((endIndex >= 0) && (endIndex > getRow()))) {
			throw new ExcelParseException("起始行或结束行参数有误！");
		}

		if ((endIndex >= 0) && (endIndex < startIndex)) {
			throw new ExcelParseException("结束行不能小于起始行！");
		}

		List buildValue = new ArrayList();
		this.buildMessage = new StringBuffer();
		setBuildPercent(0);

		endIndex = endIndex < 0 ? getRow() : endIndex;
		for (int i = startIndex; i < endIndex; i++) {
			setBuildPercent((i - startIndex) * 100 / (endIndex - startIndex));
			List getRowValue = getRowValue(i);
			if (getRowValue == null) {
				throw new ExcelParseException("第" + (i + 1) + "行数据获取失败！");
			}
			boolean validateResult = true;
			for (int m = 0; m < validationRule.length; m++) {
				String[] validateValue = new String[validationRule[m]
						.getValidateIndex().length];
				for (int n = 0; n < validateValue.length; n++) {
					validateValue[n] = ((String) getRowValue
							.get(validationRule[m].getValidateIndex()[n]
									.intValue()));
				}

				if (!validationRule[m].getValidation().validate(i,
						validationRule[m].getValidateIndex(), validateValue,
						this.buildMessage)) {
					if (this.messageEndFix != null)
						this.buildMessage.append(this.messageEndFix);
					validateResult = false;
					if (this.buildModel == STOP_ON_ROW_VALIDATION) {
						break;
					}
				}
			}
			if (validateResult) {
				buildValue.add(getRowValue);
			} else {
				if (this.buildModel == STOP_ON_VALIDATION) {
					break;
				}
			}
		}
		setBuildPercent(100);
		return buildValue;
	}

	public StringBuffer getBuildMessage() {
		return this.buildMessage;
	}

	public void close() {
		if (this.workbook != null) {
			this.sheet = null;
			this.workbook.close();
		}
	}
}
