package com.eactive.eai.rms.common.excel;

import java.io.InputStream;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ExcelSheet implements Sheet {

    private HSSFWorkbook workbook;
    private XSSFWorkbook workbook_xlsx;
    private HSSFSheet sheet;
    private XSSFSheet sheet_xlsx;
    private String    name;

    private ExcelSheet(HSSFWorkbook workbook, int sheetIndex)
        throws Exception {
        this.workbook = workbook;
        this.sheet = workbook.getSheetAt(sheetIndex);
    }
    private ExcelSheet(HSSFWorkbook workbook, int sheetIndex,String name)
        throws Exception {
        this.workbook = workbook;
        this.sheet = workbook.getSheetAt(sheetIndex);
        this.name = name;
    }    
    private ExcelSheet(XSSFWorkbook workbook_xlsx, int sheetIndex)
        throws Exception {
        this.workbook_xlsx = workbook_xlsx;
        this.sheet_xlsx = workbook_xlsx.getSheetAt(sheetIndex);
    }
    private ExcelSheet(XSSFWorkbook workbook_xlsx, int sheetIndex,String name)
        throws Exception {
        this.workbook_xlsx = workbook_xlsx;
        this.sheet_xlsx = workbook_xlsx.getSheetAt(sheetIndex);
        this.name = name;
    }
    public static ExcelSheet[] getExcelSheets(InputStream in) throws Exception {
        HSSFWorkbook workbook = new HSSFWorkbook(in);
        ExcelSheet[] sheets = new ExcelSheet[workbook.getNumberOfSheets()];

        for (int i = 0; i < sheets.length; i++) {
            sheets[i] = new ExcelSheet(workbook, i, workbook.getSheetName(i));
        }
        return sheets;
    }
    public static ExcelSheet[] getExcelSheetsForXlsx(InputStream in) throws Exception {
        XSSFWorkbook workbook_xlsx = new XSSFWorkbook(in);
        ExcelSheet[] sheets = new ExcelSheet[workbook_xlsx.getNumberOfSheets()];

        for (int i = 0; i < sheets.length; i++) {
            sheets[i] = new ExcelSheet(workbook_xlsx, i,workbook_xlsx.getSheetName(i));
        }
        return sheets;
    }

    public String getCellString(int row, int column) throws Exception {
        if(sheet == null) {
        	throw new Exception("cannt read excel file SHEET is null : " + (row + 1));
        }
    	HSSFRow hrow = sheet.getRow(row);

        if (hrow == null) {
            throw new Exception("cannt read excel file line number : " + (row + 1));
        }

        HSSFCell cell = hrow.getCell((short) column);

        if (cell == null) {
        	//logger.warn("Excel 화일의 '" + (row + 1) + "' 번째 라인의 '" + column + "' 번째 컬럼을 읽을 수 없읍니다. -> zero size string으로 대체.");
        	return "";
        }
        
        try {
			switch (cell.getCellType()) {
			
			case HSSFCell.CELL_TYPE_NUMERIC :
				return "" + ((int) cell.getNumericCellValue());
			default :
		        if (cell.getStringCellValue() == null) { 	
		            return "";
		        }
				return cell.getStringCellValue().trim();
			}
        } catch(Exception e) {
    		throw new Exception("getCellString(" + (row+1) + "," + column + ") operation failed", e);
        }
    }
    public String getCellStringForXlsx(int row, int column) throws Exception {
        XSSFRow xrow = sheet_xlsx.getRow(row);

        if (xrow == null) {
            throw new Exception("cannt read excel file line number : " + (row + 1));
        }

        XSSFCell cell = xrow.getCell((short) column);

        if (cell == null) {
        	//logger.warn("Excel 화일의 '" + (row + 1) + "' 번째 라인의 '" + column + "' 번째 컬럼을 읽을 수 없읍니다. -> zero size string으로 대체.");
        	return "";
        }
        
        try {
			switch (cell.getCellType()) {
			
			case HSSFCell.CELL_TYPE_NUMERIC :
				return "" + ((int) cell.getNumericCellValue());
			default :
		        if (cell.getStringCellValue() == null) { 	
		            return "";
		        }
				return cell.getStringCellValue().trim();
			}
        } catch(Exception e) {
    		throw new Exception("getCellString(" + (row+1) + "," + column + ") operation failed", e);
        }
    }

    public int getCellInt(int row, int column) throws Exception {
    	HSSFCell cell = sheet.getRow(row).getCell((short) column);
    	try {
    		if (cell==null) {
    			throw new Exception("getCellInt(" + row + "," + column + ") operation failed - cell value is null");
    			//return 0;
    		}
    		switch (cell.getCellType()) {
    		case HSSFCell.CELL_TYPE_NUMERIC :
    			return (int) cell.getNumericCellValue();
    		default :
    			return Integer.parseInt(cell.getStringCellValue().trim());
    		}
    	} catch(Exception e) {
    		throw new Exception("getCellInt(" + (row+1) + "," + column + ") operation failed", e);
    	}
    }
    public int getCellIntForXlsx(int row, int column) throws Exception {
    	XSSFCell cell = sheet_xlsx.getRow(row).getCell((short) column);
    	try {
    		if (cell==null) {
    			throw new Exception("getCellInt(" + row + "," + column + ") operation failed - cell value is null");
    			//return 0;
    		}
    		switch (cell.getCellType()) {
    		case XSSFCell.CELL_TYPE_NUMERIC :
    			return (int) cell.getNumericCellValue();
    		default :
    			return Integer.parseInt(cell.getStringCellValue().trim());
    		}
    	} catch(Exception e) {
    		throw new Exception("getCellInt(" + (row+1) + "," + column + ") operation failed", e);
    	}
    }
    public boolean existsRow(int row) throws Exception {
    	 if(sheet == null) {
         	throw new Exception("cannt read excel file SHEET is null : " + (row + 1));
         }
    	if (row > sheet.getLastRowNum())
    		return false;
    	if (this.getCellValue(row, 0) == null || getCellValue(row, 1) == null)
    		return false;
    	return true;
    }
    public boolean existsRowForXlsx(int row) throws Exception {
    	if (row > sheet_xlsx.getLastRowNum())
    		return false;
    	if (this.getCellValueForXlsx(row, 0) == null || getCellValueForXlsx(row, 1) == null)
    		return false;
    	return true;
    }
    
    public boolean existsCell(int row, int col) throws Exception {
    	if (!existsRow(row))
    		return false;
    	if (this.getCellValue(row, col) == null)
    		return false;
    	return true;
    }   
    public boolean existsCellForXlsx(int row, int col) throws Exception {
    	if (!existsRowForXlsx(row))
    		return false;
    	if (this.getCellValueForXlsx(row, col) == null)
    		return false;
    	return true;
    }  

    public boolean isEquals(int row, int column, String value) throws Exception {
        return getCellString(row, column).equals(value);
    }

    public String getCellValue(int row, int column) {
        HSSFRow hrow = sheet.getRow(row);        
        if (hrow == null)
        	return null;        
        HSSFCell cell = hrow.getCell((short) column);        
        if (cell == null)
        	return null;

        switch (cell.getCellType()) {
            case HSSFCell.CELL_TYPE_BLANK:
                return "";
    
            case HSSFCell.CELL_TYPE_BOOLEAN:
                return Boolean.toString(cell.getBooleanCellValue());
    
            case HSSFCell.CELL_TYPE_ERROR:
                return Byte.toString(cell.getErrorCellValue());
    
            case HSSFCell.CELL_TYPE_FORMULA:
                return cell.getCellFormula();
    
            case HSSFCell.CELL_TYPE_NUMERIC:
                return Double.toString(cell.getNumericCellValue());
    
            case HSSFCell.CELL_TYPE_STRING:
                return cell.getStringCellValue();
        }

        return null;
    }
    public String getCellValueForXlsx(int row, int column) {
        XSSFRow xrow = sheet_xlsx.getRow(row);        
        if (xrow == null)
        	return null;        
        XSSFCell cell = xrow.getCell((short) column);        
        if (cell == null)
        	return null;

        switch (cell.getCellType()) {
            case XSSFCell.CELL_TYPE_BLANK:
                return "";
    
            case XSSFCell.CELL_TYPE_BOOLEAN:
                return Boolean.toString(cell.getBooleanCellValue());
    
            case XSSFCell.CELL_TYPE_ERROR:
                return Byte.toString(cell.getErrorCellValue());
    
            case XSSFCell.CELL_TYPE_FORMULA:
                return cell.getCellFormula();
    
            case XSSFCell.CELL_TYPE_NUMERIC:
                return Double.toString(cell.getNumericCellValue());
    
            case XSSFCell.CELL_TYPE_STRING:
                return cell.getStringCellValue();
        }

        return null;
    }
    public String getName(){
    	return this.name;
    }
    public String toString() {
    	StringBuffer sb = new StringBuffer();
    	sb.append("Workbook - " + (this.workbook==null?"":this.workbook.toString()) + "\n");
    	sb.append("workbook_xlsx - " + (this.workbook_xlsx==null?"":this.workbook_xlsx.toString()) + "\n");
    	
    	for (int i=0; i<sheet.getLastRowNum(); i++) {
    		if (sheet.getRow(i) != null && sheet.getRow(i).getCell((short) 0) != null)
    			sb.append("sheet[" + i + "] : " + sheet.getRow(i).getCell((short) 0).getStringCellValue() + "\n");
    	}
    	return sb.toString();
    }   
}
