package net.educoder.ecsonar.utils;

import net.educoder.ecsonar.model.Metrics;
import net.educoder.ecsonar.model.api.Person;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class ExcelUtil {


    private static final String EXCEL_XLS = "xls";
    private static final String EXCEL_XLSX = "xlsx";

    private static final String SCORE ="IFERROR(分数转化说明!B$4*V#line+分数转化说明!G$4*W#line+分数转化说明!L$4*X#line,\" \")";
    private static final String BUG ="IFERROR(100-SUMPRODUCT(代码检测结果!D#line:G#line,分数转化说明!B$6:E$6)/代码检测结果!$T#line*100,\" \")";
    private static final String VULNERABILITY ="IFERROR(100-SUMPRODUCT(代码检测结果!I#line:L#line,分数转化说明!G$6:J$6)/代码检测结果!$T#line*100,\" \")";
    private static final String CODE_SMELL ="IFERROR(100-SUMPRODUCT(代码检测结果!N#line:Q#line,分数转化说明!L$6:O$6)/代码检测结果!$T#line*100,\" \")";


    /**
     * 检查此用户是否查验过
     *
     * @param excelPath
     * @param uid
     * @return
     */
    public static boolean isChecked(String excelPath, String uid) {
        try {
            File finalXlsxFile = new File(excelPath);
            Workbook workBook = getWorkbok(finalXlsxFile);
            Sheet sheet = workBook.getSheetAt(0);
            int rowNumber = sheet.getLastRowNum();
            for (int i = 0; i < rowNumber + 1; ++i) {
                Row row = sheet.getRow(3 + i);
                Cell cell = row.getCell(1);
                cell.setCellType(CellType.STRING);
                if (StringUtils.equals(cell.getStringCellValue(), uid)) {
                    return true;
                }
            }
        } catch (Exception e) {
            return false;
        }

        return false;
    }

    public static Workbook openExcel(String excelPath) throws IOException {
        // 读取Excel文档
        File finalXlsxFile = new File(excelPath);
        Workbook workBook = getWorkbok(finalXlsxFile);

        return workBook;
    }

    public static void writeMetrics(Metrics metrics, String uid,
                                    String name,
                                    Workbook workBook, int index) throws IOException {


        // sheet 对应一个工作页
        Sheet sheet = workBook.getSheetAt(0);


        /**
         * 删除原有数据，除了属性列
         */
        int rowNumber = sheet.getLastRowNum();    // 第一行从0开始算

        //从第三行开始
        Row newRow = null;

        for (int i = 3; i < rowNumber+1; ++i) {
            Row row = sheet.getRow(i);

            if (row != null) {
                Cell cell = row.getCell(1);

                cell.setCellType(CellType.STRING);
                if (StringUtils.isEmpty(cell.getStringCellValue())
                        || StringUtils.equals(cell.getStringCellValue(), uid)) {

                    newRow = row;
                    break;
                }
            }
        }

        if (newRow == null) {
            newRow = sheet.createRow(rowNumber+1);
        }

        //一直往下找，直到找到空的，或者与学号匹配的行，进行写入
        //学号
        Cell uidCell = newRow.createCell(1);
        uidCell.setCellType(CellType.STRING);
        uidCell.setCellValue(uid);

        Cell cell2 = newRow.createCell(2);
        cell2.setCellType(CellType.STRING);
        cell2.setCellValue(name);

        int offset = 0;
        if (index == 2) {
            offset = 17;
        }
        Cell cell3 = newRow.createCell(3 + offset);
        cell3.setCellType(CellType.NUMERIC);
        cell3.setCellValue(metrics.getBlock_bugs());

        Cell cell4 = newRow.createCell(4 + offset);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getCritical_bugs());

        cell4 = newRow.createCell(5 + offset);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getMajor_bugs());

        cell4 = newRow.createCell(6 + offset);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getMinor_bugs());

        cell4 = newRow.createCell(7 + offset);
        cell4.setCellType(CellType.STRING);
        cell4.setCellValue(metrics.getBugs());


        cell4 = newRow.createCell(8 + offset);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getBlock_violations());

        cell4 = newRow.createCell(9 + offset);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getCritical_violations());

        cell4 = newRow.createCell(10 + offset);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getMajor_violations());

        cell4 = newRow.createCell(11 + offset);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getMinor_violations());

        cell4 = newRow.createCell(12 + offset);
        cell4.setCellType(CellType.STRING);
        cell4.setCellValue(metrics.getViolations());


        cell4 = newRow.createCell(13 + offset);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getBlock_code_smells());


        cell4 = newRow.createCell(14 + offset);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getCritical_code_smells());

        cell4 = newRow.createCell(15 + offset);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getMajor_violations());

        cell4 = newRow.createCell(16 + offset);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getMinor_code_smells());

        cell4 = newRow.createCell(17 + offset);
        cell4.setCellType(CellType.STRING);
        cell4.setCellValue(metrics.getCode_smells());


        cell4 = newRow.createCell(18 + offset);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getComplexity());

        cell4 = newRow.createCell(19 + offset);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getLines());

    }


    /**
     * 根据template1写入excel
     * @param metrics
     * @param uid
     * @param name
     * @param workBook
     * @throws IOException
     */
    public static void writeToTemplateOne(Metrics metrics, String uid,
                                    String name,
                                    Workbook workBook) throws IOException {


        // sheet 对应一个工作页
        Sheet sheet = workBook.getSheetAt(0);
        sheet.setForceFormulaRecalculation(true);
        CellStyle cellStyle = workBook.createCellStyle();
        cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00"));


        /**
         * 删除原有数据，除了属性列
         */
        int rowNumber = sheet.getLastRowNum();    // 第一行从0开始算

        //从第三行开始
        Row newRow = null;

        for (int i = 3; i < rowNumber+1; ++i) {
            Row row = sheet.getRow(i);

            if (row != null) {
                Cell cell = row.getCell(1);

                cell.setCellType(CellType.STRING);
                if (StringUtils.isEmpty(cell.getStringCellValue())
                        || StringUtils.equals(cell.getStringCellValue(), uid)) {

                    newRow = row;
                    break;
                }
            }
        }

        if (newRow == null) {
            newRow = sheet.createRow(rowNumber+1);
        }

        //一直往下找，直到找到空的，或者与学号匹配的行，进行写入
        //学号
        Cell uidCell = newRow.createCell(1);
        uidCell.setCellType(CellType.STRING);
        uidCell.setCellValue(uid);

        Cell cell2 = newRow.createCell(2);
        cell2.setCellType(CellType.STRING);
        cell2.setCellValue(name);


        Cell cell3 = newRow.createCell(3);
        cell3.setCellType(CellType.NUMERIC);
        cell3.setCellValue(metrics.getBlock_bugs());

        Cell cell4 = newRow.createCell(4);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getCritical_bugs());

        cell4 = newRow.createCell(5);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getMajor_bugs());

        cell4 = newRow.createCell(6);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getMinor_bugs());

        cell4 = newRow.createCell(7);
        cell4.setCellType(CellType.STRING);
        cell4.setCellValue(metrics.getBugs());


        cell4 = newRow.createCell(8);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getBlock_violations());

        cell4 = newRow.createCell(9);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getCritical_violations());

        cell4 = newRow.createCell(10 );
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getMajor_violations());

        cell4 = newRow.createCell(11 );
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getMinor_violations());

        cell4 = newRow.createCell(12);
        cell4.setCellType(CellType.STRING);
        cell4.setCellValue(metrics.getViolations());


        cell4 = newRow.createCell(13);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getBlock_code_smells());


        cell4 = newRow.createCell(14);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getCritical_code_smells());

        cell4 = newRow.createCell(15);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getMajor_violations());

        cell4 = newRow.createCell(16);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getMinor_code_smells());

        cell4 = newRow.createCell(17);
        cell4.setCellType(CellType.STRING);
        cell4.setCellValue(metrics.getCode_smells());


        cell4 = newRow.createCell(18);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getComplexity());

        cell4 = newRow.createCell(19);
        cell4.setCellType(CellType.NUMERIC);
        cell4.setCellValue(metrics.getLines());


        String rowStr = String.valueOf(rowNumber+2);
        cell4 = newRow.createCell(20);
        cell4.setCellType(CellType.FORMULA);
        cell4.setCellStyle(cellStyle);
        cell4.setCellFormula(SCORE.replaceAll("#line", rowStr));

        cell4 = newRow.createCell(21);
        cell4.setCellType(CellType.FORMULA);
        cell4.setCellStyle(cellStyle);
        cell4.setCellFormula(BUG.replaceAll("#line", rowStr));

        cell4 = newRow.createCell(22);
        cell4.setCellType(CellType.FORMULA);
        cell4.setCellStyle(cellStyle);
        cell4.setCellFormula(VULNERABILITY.replaceAll("#line", rowStr));

        cell4 = newRow.createCell(23);
        cell4.setCellType(CellType.FORMULA);
        cell4.setCellStyle(cellStyle);
        cell4.setCellFormula(CODE_SMELL.replaceAll("#line", rowStr));

    }


    public static void saveExcel(Workbook workBook, String excelPath) throws Exception {
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(excelPath);
            workBook.write(out);

        } finally {
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 判断Excel的版本,获取Workbook
     *
     * @return
     * @throws IOException
     */
    public static Workbook getWorkbok(File file) throws IOException {
        Workbook wb = null;
        FileInputStream in = new FileInputStream(file);
        if (file.getName().endsWith(EXCEL_XLS)) {     //Excel&nbsp;2003
            wb = new HSSFWorkbook(in);
        } else if (file.getName().endsWith(EXCEL_XLSX)) {    // Excel 2007/2010
            wb = new XSSFWorkbook(in);
        }
        return wb;
    }

    /**
     * 读取excel
     * @param excelPath
     * @return
     */
    public static List<Person> readExcel(String excelPath) throws IOException {
        Workbook workbook = getWorkbok(new File(excelPath));
        Sheet sheet = workbook.getSheetAt(0);

        int lastRowNum = sheet.getLastRowNum();

        List<Person> personList = new ArrayList<>(lastRowNum+1);

        // 从第二行开始读
        for (int i = 1; i <= lastRowNum; i++) {
            Row row = sheet.getRow(i);

            String name = row.getCell(0).getStringCellValue();
            String uid = row.getCell(1).getStringCellValue();
            String downloadUrl = row.getCell(2).getStringCellValue();

            Person person = new Person();
            person.setName(name);
            person.setUid(uid);
            person.setDownloadUrl(downloadUrl);
            personList.add(person);
        }

        return personList;
    }

}
