package net.w_horse.excelpojo.excel;

import java.lang.annotation.Annotation;


import net.w_horse.excelpojo.annotation.ExcelPOJOAnnotationParser;
import net.w_horse.excelpojo.xml.ExcelPOJOXmlParser;
import net.w_horse.excelpojo.xml.tag.RetrieveFrom;
import net.w_horse.excelpojo.xml.tag.Use;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.w3c.dom.Element;

public class LabeledCellSeeker extends AbstractCellSeeker {

	private String label;
	private String retrieveFrom;
	private String margedLabel;
	private boolean margedRows = false;

	@Override
	public void set(Element element, ExcelPOJOXmlParser parser) {
		parser.setCellSeeker(element, this);
	}

	@Override
	public void set(Annotation annotation, ExcelPOJOAnnotationParser parser) {
		parser.setCellSeeker(annotation, this);
	}

	@Override
	public boolean verify() throws IllegalArgumentException {
		if ((getLabel() == null) || getLabel().isEmpty()) {
			throw new IllegalArgumentException("The label is not specified.");
		}
		return true;
	}

	@Override
	public Object seekCellValue(HSSFSheet sheet, Class<?> requiredType) throws CellNotFoundException {
		return getCellValue(sheet, seekCellPosition(sheet), requiredType);
	}

	@Override
	protected Offset seekCellPosition(HSSFSheet sheet) throws CellNotFoundException {
		return seekCellPosition(sheet, new Offset(), new Offset());
	}

	@Override
	protected Offset seekCellPosition(HSSFSheet sheet, Offset basePosition, Offset offset) throws CellNotFoundException {
		Offset newOffset = parseOffset(offset);
		int rowIndex = (sheet.getFirstRowNum() > basePosition.rowIndex ? sheet.getFirstRowNum() : basePosition.rowIndex);
		for (; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
			HSSFRow row = sheet.getRow(rowIndex);
			if (row == null) continue;

			int colIndex = (row.getFirstCellNum() > basePosition.colIndex ? row.getFirstCellNum() : basePosition.colIndex);
			for (; colIndex <= row.getLastCellNum(); colIndex++) {
				HSSFCell cell = row.getCell(colIndex -1);
				if (cell == null) continue;

				if (getCellValue(cell, String.class).equals(getLabel())) {
					return new Offset(cell.getRowIndex() + newOffset.rowIndex,
								cell.getColumnIndex() + newOffset.colIndex);
				}
			}
		}
		if (Use.equalsIgnoreCase(Use.REQUIRED, getUse())) {
			throw new CellNotFoundException("label='" + getLabel() + "'");
		}

		return null;
	}
	@Override
	public void setValue(HSSFSheet sheet, Object value) throws CellNotFoundException {
		setCellValue(getCell(sheet, seekCellPosition(sheet)), value);
	}

	protected void setValue(HSSFSheet sheet, Offset basePosition,
			Offset offset, Object value) throws CellNotFoundException {
		setCellValue(getCell(sheet, seekCellPosition(sheet, basePosition, offset)), value);
	}

	private Offset parseOffset(Offset offset) {
		Offset newOoffset;

		String retrieveFrom = getRetrieveFrom();
		int margedLabel = 0;
		if ((getMargedLabel() != null) && !getMargedLabel().isEmpty()) {
			margedLabel = Integer.parseInt(getMargedLabel());
		}
		if (RetrieveFrom.equalsIgnoreCase(RetrieveFrom.LEFT, retrieveFrom)) {
			newOoffset = new Offset(margedLabel, -1);
		} else if (RetrieveFrom.equalsIgnoreCase(RetrieveFrom.RIGHT, retrieveFrom)) {
			newOoffset = new Offset(margedLabel, 1);
		} else {	// RETRIEVE_FROM_BOTTOM
			newOoffset = new Offset(1, margedLabel);
		}
		newOoffset.rowIndex += offset.rowIndex;
		newOoffset.colIndex += offset.colIndex;

		return newOoffset;
	}

	public void setLabel(String label) {
		this.label = label;
	}

	public String getLabel() {
		return label;
	}

	public void setRetrieveFrom(String retrieveFrom) {
		this.retrieveFrom = retrieveFrom;
	}

	public String getRetrieveFrom() {
		return retrieveFrom;
	}

	public void setMargedLabel(String margedLabel) {
		this.margedLabel = margedLabel;
	}

	public String getMargedLabel() {
		return margedLabel;
	}

	public boolean isMargedRows() {
	    return margedRows;
	}

	public void setMargedRows(boolean margedRows) {
		this.margedRows = margedRows;
	}


}
