package com.app.datahandling;


import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;

//import org.apache.xpath.operations.String;

/**
 * Created by OS344312 on 8/29/2016.
 */
public class ExcelReaderX {

    private XSSFWorkbook xssfWorkbook = null;

    private boolean allSheetsDone = false;

    private List<String> sheetNames = new ArrayList<>();

    private Map<String, Map<String, Map<String, String>>> allSheetsMap = new LinkedHashMap<>();

    private final static Logger logger = LoggerFactory.getLogger(ExcelReaderX.class);

    public List<String> getSheetNames() {
        return sheetNames;
    }

    public ExcelReaderX(String fileName){
        FileInputStream fs = null;
        try {
            fs = new FileInputStream(fileName);
            xssfWorkbook = new XSSFWorkbook(fs);
            int numberOfSheets = xssfWorkbook.getNumberOfSheets();
            for(int i = 0; i < numberOfSheets; i++) {
                sheetNames.add(xssfWorkbook.getSheetName(i));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public Map<String, Map<String, Map<String, String>>> convertAllSheetsToMap() {

        if(allSheetsDone) {
            return allSheetsMap;
        } else {
            for(String sheetName : sheetNames) {
                if(allSheetsMap.containsKey(sheetName)) {
                    continue;
                }
                allSheetsMap.put(sheetName, convertSheetToMap(xssfWorkbook.getSheet(sheetName)));
            }
            allSheetsDone = true;
        }
        return allSheetsMap;
    }

    public Map<String, Map<String, String>> getSheetAsMap(String sheetName) {

        try {
            if (!sheetNames.contains(sheetName)) {

                throw new RuntimeException(sheetName + " not found");
            }
        }catch (Exception e){
            logger.error("Error", Arrays.toString(e.getStackTrace()));
        }

        Map<String, Map<String, String>> sheetMap = allSheetsMap.get(sheetName);

        if(sheetMap == null) {
            sheetMap = convertSheetToMap(xssfWorkbook.getSheet(sheetName));
            allSheetsMap.put(sheetName, sheetMap);
        }

        return sheetMap;
    }

    private Map<String, Map<String, String>> convertSheetToMap(XSSFSheet sheet) {
        Map<String, Map<String, String>> sheetMap = new LinkedHashMap();

        int rows = sheet.getPhysicalNumberOfRows();
        int cols = sheet.getRow(0).getLastCellNum();

        XSSFRow headerRow = sheet.getRow(0);
        List<String> headerRowNames = new ArrayList<>();

        for (int i = 0; i < cols; i++) {
            headerRowNames.add(headerRow.getCell(i).getStringCellValue());
        }
        //System.out.println(sheet.getSheetName());
        for (int i = 1; i < rows; i++) {
            Map<String, String> rowMap = new LinkedHashMap<>();
            XSSFRow dataRow = sheet.getRow(i);
            String key = dataRow.getCell(0).getStringCellValue();
            if (key == null || key.trim().length() == 0) {
                continue;
            }
            //System.out.println("TestCase = " + key);
            for (int j = 0; j < cols; j++) {
                XSSFCell cell = dataRow.getCell(j);
                if (cell != null) {
                    rowMap.put(headerRowNames.get(j), cell.toString());
                } else {
                    rowMap.put(headerRowNames.get(j), null);
                }

            }
            sheetMap.put(key, rowMap);
        }
        return sheetMap;
    }
}

