/**
 * Report phase: merge with loaded report/summary, write report.json, file_map.json, report.csv, content_directory_paths.json.
 * Expects ctx: outputHandle, fileMap, mergeResult, options, writeFileToDir, pathDirname.
 */
(function () {
  'use strict';

  var g = typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : this);
  g.GphotoPipelinePhases = g.GphotoPipelinePhases || {};

  g.GphotoPipelinePhases.runReport = function (ctx, log) {
    log = log || function () {};
    var outputHandle = ctx.outputHandle;
    var fileMap = ctx.fileMap;
    var mergeResult = ctx.mergeResult;
    var options = ctx.options || {};
    var dryRun = options.dryRun === true;
    var writeFileToDir = ctx.writeFileToDir;
    var pathDirname = ctx.pathDirname;

    if (dryRun) return Promise.resolve();
    var report = mergeResult.report;
    log('Writing report...');
    var loadReportPromise = outputHandle.getFileHandle('report.json').then(function (h) {
      return h.getFile().then(function (f) { return f.text(); }).then(function (t) {
        try { return JSON.parse(t); } catch (e) { return null; }
      });
    }).catch(function () { return null; });
    var loadSummaryPromise = outputHandle.getFileHandle('summary_report.json').then(function (h) {
      return h.getFile().then(function (f) { return f.text(); }).then(function (t) {
        try { return JSON.parse(t); } catch (e) { return null; }
      });
    }).catch(function () { return null; });
    return Promise.all([loadReportPromise, loadSummaryPromise]).then(function (loadResults) {
      var loadedReport = loadResults[0];
      var loadedSummary = loadResults[1];
      var mergedReport = report;
      if (loadedReport && typeof loadedReport === 'object') {
        var remerged = report.remerged || [];
        var prevNotMerged = (loadedReport.not_merged || loadedReport.transferred || []).filter(function (f) {
          return remerged.indexOf(f) === -1;
        });
        var notMerged = prevNotMerged.concat(report.transferred || []);
        mergedReport = {
          merged: (loadedReport.merged || []).concat(report.merged || []),
          transferred: (loadedReport.transferred || []).concat(report.transferred || []),
          not_merged: notMerged,
          remerged: (loadedReport.remerged || []).concat(remerged),
          errors: (loadedReport.errors || []).concat(report.errors || []),
          moved_from_lake: (loadedReport.moved_from_lake || []).concat(report.moved_from_lake || []),
          exif_restored: (loadedReport.exif_restored || []).concat(report.exif_restored || []),
          exif_replaced: (loadedReport.exif_replaced || []).concat(report.exif_replaced || []),
          skipped_existing: (loadedReport.skipped_existing || []).concat(report.skipped_existing || []),
          moved_to_duplicates: (loadedReport.moved_to_duplicates || []).concat(report.moved_to_duplicates || []),
          problematic_files: (loadedReport.problematic_files || []).concat(report.problematic_files || []),
          dry_run: report.dry_run,
          timestamp: report.timestamp,
          generated_at: report.generated_at,
          extension_version: report.extension_version
        };
      } else {
        mergedReport.not_merged = (report.transferred || []).slice();
      }
      var reportJson = JSON.stringify(mergedReport, null, 2);
      var fileMapJson = JSON.stringify(fileMap, null, 2);
      function csvEscape(s) {
        if (s == null) return '';
        var t = String(s);
        if (t.indexOf(',') >= 0 || t.indexOf('"') >= 0 || t.indexOf('\n') >= 0) {
          return '"' + t.replace(/"/g, '""') + '"';
        }
        return t;
      }
      var reportCsv = 'action,file\n' +
        (mergedReport.merged || []).map(function (f) { return 'merged,' + csvEscape(f); }).join('\n') + '\n' +
        (mergedReport.exif_restored || []).map(function (f) { return 'exif_restored,' + csvEscape(f); }).join('\n') + '\n' +
        (mergedReport.exif_replaced || []).map(function (f) { return 'exif_replaced,' + csvEscape(f); }).join('\n') + '\n' +
        (mergedReport.transferred || []).map(function (f) { return 'transferred,' + csvEscape(f); }).join('\n') + '\n' +
        (mergedReport.moved_from_lake || []).map(function (f) { return 'moved_from_lake,' + csvEscape(f); }).join('\n') + '\n' +
        (mergedReport.skipped_existing || []).map(function (f) { return 'skipped_existing,' + csvEscape(f); }).join('\n') + '\n' +
        (mergedReport.moved_to_duplicates || []).map(function (f) { return 'moved_to_duplicates,' + csvEscape(f); }).join('\n') + '\n' +
        (mergedReport.errors || []).map(function (e) { return 'error,' + csvEscape(e); }).join('\n') + '\n' +
        (mergedReport.problematic_files || []).map(function (p) { return 'problematic,' + csvEscape((p.file || p.path || '') + (p.reason ? ': ' + p.reason : '')); }).join('\n');
      var contentPaths = {};
      for (var fn in fileMap) {
        if (Object.prototype.hasOwnProperty.call(fileMap, fn)) {
          var rec = fileMap[fn];
          contentPaths[fn] = pathDirname(rec.original_path || '') || rec.parent_folder || '';
        }
      }
      var contentPathsJson = JSON.stringify(contentPaths, null, 2);
      ctx.loadedSummary = loadedSummary;
      var notMergedListJson = JSON.stringify(mergedReport.not_merged || [], null, 2);
      var writeChain = writeFileToDir(outputHandle, 'report.json', new TextEncoder().encode(reportJson)).then(function () {
        return writeFileToDir(outputHandle, 'file_map.json', new TextEncoder().encode(fileMapJson));
      }).then(function () {
        return writeFileToDir(outputHandle, 'report.csv', new TextEncoder().encode(reportCsv));
      }).then(function () {
        return writeFileToDir(outputHandle, 'content_directory_paths.json', new TextEncoder().encode(contentPathsJson));
      }).then(function () {
        return writeFileToDir(outputHandle, 'not_merged_list.json', new TextEncoder().encode(notMergedListJson));
      });
      if (typeof GphotoMediaIndex !== 'undefined' && GphotoMediaIndex.serializeIndexForCache && ctx.lakeFiles && mergeResult.index) {
        var reportForRemaining = mergeResult.report;
        var mergedNames = (reportForRemaining.merged || []);
        var transferredNames = (reportForRemaining.transferred || []);
        var outSet = {};
        for (var i = 0; i < mergedNames.length; i++) outSet[mergedNames[i]] = true;
        for (var j = 0; j < transferredNames.length; j++) outSet[transferredNames[j]] = true;
        var remainingNames = [];
        for (var k = 0; k < ctx.lakeFiles.length; k++) {
          var fn = ctx.lakeFiles[k].name;
          if (!outSet[fn]) remainingNames.push(fn);
        }
        var cacheObj = GphotoMediaIndex.serializeIndexForCache(mergeResult.index, remainingNames);
        if (cacheObj) {
          writeChain = writeChain.then(function () {
            return writeFileToDir(outputHandle, 'lake_index_cache.json', new TextEncoder().encode(JSON.stringify(cacheObj, null, 2)));
          });
        }
      }
      return writeChain.catch(function () {
        report.errors.push('Report files could not be written to the output folder. It may have been moved, deleted, or permission was revoked.');
        return Promise.resolve();
      });
    });
  };
})();
