package com.github.mkolisnyk.cucumber.reporting;

import java.io.File;
import java.io.InputStream;
import java.util.Locale;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;

import com.github.mkolisnyk.cucumber.reporting.interfaces.ConfigurableReport;
import com.github.mkolisnyk.cucumber.reporting.types.beans.BreakdownDataBean;
import com.github.mkolisnyk.cucumber.reporting.types.breakdown.BreakdownReportInfo;
import com.github.mkolisnyk.cucumber.reporting.types.breakdown.BreakdownReportModel;
import com.github.mkolisnyk.cucumber.reporting.types.breakdown.BreakdownStats;
import com.github.mkolisnyk.cucumber.reporting.types.breakdown.BreakdownTable;
import com.github.mkolisnyk.cucumber.reporting.types.enums.CucumberReportError;
import com.github.mkolisnyk.cucumber.reporting.types.enums.CucumberReportLink;
import com.github.mkolisnyk.cucumber.reporting.types.enums.CucumberReportTypes;
import com.github.mkolisnyk.cucumber.reporting.types.result.CucumberFeatureResult;
import com.github.mkolisnyk.cucumber.reporting.types.result.CucumberScenarioResult;
import com.github.mkolisnyk.cucumber.runner.runtime.ExtendedRuntimeOptions;

public class CucumberBreakdownReport extends ConfigurableReport<BreakdownReportModel> {
    public CucumberBreakdownReport() {
        super();
    }
    public CucumberBreakdownReport(ExtendedRuntimeOptions extendedOptions) {
        super(extendedOptions);
    }
    private static final int TIMEOUT_MULTIPLIER = 3;

    @Override
    public int[][] getStatuses(CucumberFeatureResult[] results) {
        return null;
    }
    public void executeReport(BreakdownReportInfo info, BreakdownTable table, String[] formats) throws Exception {
        CucumberFeatureResult[] features = readFileContent(true);
        File outFile = new File(
                this.getOutputDirectory() + File.separator + this.getOutputName()
                + "-" + info.getReportSuffix() + ".html");
        BreakdownDataBean data = new BreakdownDataBean();
        data.setTitle(info.getTitle());
        if (info.getRefreshTimeout() > 0 && StringUtils.isNotBlank(info.getNextFile())) {
            data.setRefreshData(String.format(Locale.US,
                    "<meta http-equiv=\"Refresh\" content=\"%d; url=%s\" />",
                        info.getRefreshTimeout(), info.getNextFile()));
        }
        data.setTable(table);
        CucumberScenarioResult[] scenarios = new CucumberScenarioResult[] {};
        for (CucumberFeatureResult feature : features) {
            scenarios = ArrayUtils.addAll(scenarios, feature.getElements());
        }
        BreakdownStats[][] results = table.valuate(scenarios);
        data.setStats(results);
        generateReportFromTemplate(outFile, "breakdown", data);
        this.export(outFile, info.getReportSuffix(), formats, this.isImageExportable());
    }
    public void executeReport(BreakdownTable table, String[] formats) throws Exception {
        executeReport(new BreakdownReportInfo(table), table, formats);
    }
    protected void generateFrameFile(BreakdownReportModel model) throws Exception {
        InputStream is = this.getClass().getResourceAsStream("/breakdown-frame.html");
        String content = IOUtils.toString(is);
        File outFile = new File(
                this.getOutputDirectory() + File.separator + this.getOutputName()
                + "-frame.html");
        content = content.replaceAll("__THIS__", outFile.getName());
        for (BreakdownReportInfo item : model.getReportsInfo()) {
            if (item.getRefreshTimeout() > 0) {
                content = content.replaceAll("__FIRST__",
                        "./" + this.getOutputName() + "-" + item.getReportSuffix() + ".html");
                break;
            }
        }
        int totalTimeout = 0;
        for (BreakdownReportInfo item : model.getReportsInfo()) {
            if (item.getRefreshTimeout() > 0) {
                totalTimeout += item.getRefreshTimeout();
            }
        }
        totalTimeout *= TIMEOUT_MULTIPLIER;
        content = content.replaceAll("__TIMEOUT__", "" + totalTimeout);
        FileUtils.writeStringToFile(outFile, content);
    }

    @Override
    public void execute(BreakdownReportModel batch, String[] formats) throws Exception {
        boolean frameGenerated = false;
        validateParameters();
        batch.initRedirectSequence("./" + this.getOutputName() + "-");
        for (BreakdownReportInfo info : batch.getReportsInfo()) {
            if (info.getRefreshTimeout() > 0 && !frameGenerated) {
                frameGenerated = true;
                generateFrameFile(batch);
            }
            this.executeReport(info, info.getTable(), formats);
        }
    }

    @Override
    public void execute(boolean aggregate, String[] formats) throws Exception {
    }
    @Override
    public CucumberReportTypes getReportType() {
        return CucumberReportTypes.BREAKDOWN_REPORT;
    }
    @Override
    public void validateParameters() {
        Assert.assertNotNull(
            this.constructErrorMessage(CucumberReportError.NO_SOURCE_FILE, ""),
            this.getSourceFiles());
        Assert.assertNotNull(
                this.constructErrorMessage(CucumberReportError.NO_OUTPUT_DIRECTORY, ""),
                this.getOutputDirectory());
        Assert.assertNotNull(
                this.constructErrorMessage(CucumberReportError.NO_OUTPUT_NAME, ""),
                this.getOutputName());
        for (String sourceFile : this.getSourceFiles()) {
            File path = new File(sourceFile);
            Assert.assertTrue(
                    this.constructErrorMessage(CucumberReportError.NON_EXISTING_SOURCE_FILE, "")
                    + ". Was looking for path: \"" + path.getAbsolutePath() + "\"",
                    path.exists());
        }
    }
    @Override
    public CucumberReportLink getReportDocLink() {
        return CucumberReportLink.BREAKDOWN_URL;
    }
    @Override
    public void execute(BreakdownReportModel batch, boolean aggregate,
            String[] formats) throws Exception {
        execute(batch, formats);
    }
    @Override
    public void execute(File config, boolean aggregate, String[] formats)
            throws Exception {
        execute(config, formats);
    }
    @Override
    public void execute(String[] formats) throws Exception {
    }
}

@@ -3139,1162 +3139,8 @@
   %7D%0A
-    protected void generateFrameFile(BreakdownReportModel model) throws Exception %7B%0A        InputStream is = this.getClass().getResourceAsStream(%22/breakdown-frame.html%22);%0A        String content = IOUtils.toString(is);%0A        File outFile = new File(%0A                this.getOutputDirectory() + File.separator + this.getOutputName()%0A                + %22-frame.html%22);%0A        content = content.replaceAll(%22__THIS__%22, outFile.getName());%0A        for (BreakdownReportInfo item : model.getReportsInfo()) %7B%0A            if (item.getRefreshTimeout() %3E 0) %7B%0A                content = content.replaceAll(%22__FIRST__%22,%0A                        %22./%22 + this.getOutputName() + %22-%22 + item.getReportSuffix() + %22.html%22);%0A                break;%0A            %7D%0A        %7D%0A        int totalTimeout = 0;%0A        for (BreakdownReportInfo item : model.getReportsInfo()) %7B%0A            if (item.getRefreshTimeout() %3E 0) %7B%0A                totalTimeout += item.getRefreshTimeout();%0A            %7D%0A        %7D%0A        totalTimeout *= TIMEOUT_MULTIPLIER;%0A        content = content.replaceAll(%22__TIMEOUT__%22, %22%22 + totalTimeout);%0A        FileUtils.writeStringToFile(outFile, content);%0A    %7D%0A%0A
     
@@ -3141,32 +3141,32 @@
 %7D%0A    @Override%0A
+
     public void 
@@ -3242,48 +3242,8 @@
 n %7B%0A
-        boolean frameGenerated = false;%0A
     
@@ -3335,24 +3335,24 @@
 e() + %22-%22);%0A
+
         for 
@@ -3409,170 +3409,8 @@
 ) %7B%0A
-            if (info.getRefreshTimeout() %3E 0 && !frameGenerated) %7B%0A                frameGenerated = true;%0A                generateFrameFile(batch);%0A            %7D%0A
     

test fixes for breakdown report