/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBitmap.h"
#include "SkImageDecoder.h"
#include "SkOSFile.h"
#include "SkRunnable.h"
#include "SkSize.h"
#include "SkStream.h"
#include "SkTDict.h"
#include "SkThreadPool.h"

#include "SkDiffContext.h"
#include "SkImageDiffer.h"
#include "skpdiff_util.h"

SkDiffContext::SkDiffContext() {
    fDiffers = NULL;
    fDifferCount = 0;
    fThreadCount = SkThreadPool::kThreadPerCore;
}

SkDiffContext::~SkDiffContext() {
    if (NULL != fDiffers) {
        SkDELETE_ARRAY(fDiffers);
    }
}

void SkDiffContext::setAlphaMaskDir(const SkString& path) {
    if (!path.isEmpty() && sk_mkdir(path.c_str())) {
        fAlphaMaskDir = path;
    }
}

void SkDiffContext::setRgbDiffDir(const SkString& path) {
    if (!path.isEmpty() && sk_mkdir(path.c_str())) {
        fRgbDiffDir = path;
    }
}

void SkDiffContext::setWhiteDiffDir(const SkString& path) {
    if (!path.isEmpty() && sk_mkdir(path.c_str())) {
        fWhiteDiffDir = path;
    }
}

void SkDiffContext::setDiffers(const SkTDArray<SkImageDiffer*>& differs) {
    // Delete whatever the last array of differs was
    if (NULL != fDiffers) {
        SkDELETE_ARRAY(fDiffers);
        fDiffers = NULL;
        fDifferCount = 0;
    }

    // Copy over the new differs
    fDifferCount = differs.count();
    fDiffers = SkNEW_ARRAY(SkImageDiffer*, fDifferCount);
    differs.copy(fDiffers);
}

static SkString get_common_prefix(const SkString& a, const SkString& b) {
    const size_t maxPrefixLength = SkTMin(a.size(), b.size());
    SkASSERT(maxPrefixLength > 0);
    for (size_t x = 0; x < maxPrefixLength; ++x) {
        if (a[x] != b[x]) {
            SkString result;
            result.set(a.c_str(), x);
            return result;
        }
    }
    if (a.size() > b.size()) {
        return b;
    } else {
        return a;
    }
}

void SkDiffContext::addDiff(const char* baselinePath, const char* testPath) {
    // Load the images at the paths
    SkBitmap baselineBitmap;
    SkBitmap testBitmap;
    if (!SkImageDecoder::DecodeFile(baselinePath, &baselineBitmap)) {
        SkDebugf("Failed to load bitmap \"%s\"\n", baselinePath);
        return;
    }
    if (!SkImageDecoder::DecodeFile(testPath, &testBitmap)) {
        SkDebugf("Failed to load bitmap \"%s\"\n", testPath);
        return;
    }

    // Setup a record for this diff
    fRecordMutex.acquire();
    DiffRecord* newRecord = fRecords.addToHead(DiffRecord());
    fRecordMutex.release();

    // compute the common name
    SkString baseName = SkOSPath::SkBasename(baselinePath);
    SkString testName = SkOSPath::SkBasename(testPath);
    newRecord->fCommonName = get_common_prefix(baseName, testName);

    newRecord->fBaselinePath = baselinePath;
    newRecord->fTestPath = testPath;
    newRecord->fSize = SkISize::Make(baselineBitmap.width(), baselineBitmap.height());

    // only generate diff images if we have a place to store them
    SkImageDiffer::BitmapsToCreate bitmapsToCreate;
    bitmapsToCreate.alphaMask = !fAlphaMaskDir.isEmpty();
    bitmapsToCreate.rgbDiff = !fRgbDiffDir.isEmpty();
    bitmapsToCreate.whiteDiff = !fWhiteDiffDir.isEmpty();

    // Perform each diff
    for (int differIndex = 0; differIndex < fDifferCount; differIndex++) {
        SkImageDiffer* differ = fDiffers[differIndex];

        // Copy the results into data for this record
        DiffData& diffData = newRecord->fDiffs.push_back();
        diffData.fDiffName = differ->getName();

        if (!differ->diff(&baselineBitmap, &testBitmap, bitmapsToCreate, &diffData.fResult)) {
            // if the diff failed, record -1 as the result
            // TODO(djsollen): Record more detailed information about exactly what failed.
            // (Image dimension mismatch? etc.)  See http://skbug.com/2710 ('make skpdiff
            // report more detail when it fails to compare two images')
            diffData.fResult.result = -1;
            continue;
        }

        if (bitmapsToCreate.alphaMask
                && SkImageDiffer::RESULT_CORRECT != diffData.fResult.result
                && !diffData.fResult.poiAlphaMask.empty()
                && !newRecord->fCommonName.isEmpty()) {

            newRecord->fAlphaMaskPath = SkOSPath::SkPathJoin(fAlphaMaskDir.c_str(),
                                                             newRecord->fCommonName.c_str());

            // compute the image diff and output it
            SkBitmap copy;
            diffData.fResult.poiAlphaMask.copyTo(&copy, kN32_SkColorType);
            SkImageEncoder::EncodeFile(newRecord->fAlphaMaskPath.c_str(), copy,
                                       SkImageEncoder::kPNG_Type, 100);

            // cleanup the existing bitmap to free up resources;
            diffData.fResult.poiAlphaMask.reset();

            bitmapsToCreate.alphaMask = false;
        }

        if (bitmapsToCreate.rgbDiff
                && SkImageDiffer::RESULT_CORRECT != diffData.fResult.result
                && !diffData.fResult.rgbDiffBitmap.empty()
                && !newRecord->fCommonName.isEmpty()) {
            // TODO(djsollen): Rather than taking the max r/g/b diffs that come back from
            // a particular differ and storing them as toplevel fields within
            // newRecord, we should extend outputRecords() to report optional
            // fields for each differ (not just "result" and "pointsOfInterest").
            // See http://skbug.com/2712 ('allow skpdiff to report different sets
            // of result fields for different comparison algorithms')
            newRecord->fMaxRedDiff = diffData.fResult.maxRedDiff;
            newRecord->fMaxGreenDiff = diffData.fResult.maxGreenDiff;
            newRecord->fMaxBlueDiff = diffData.fResult.maxBlueDiff;

            newRecord->fRgbDiffPath = SkOSPath::SkPathJoin(fRgbDiffDir.c_str(),
                                                           newRecord->fCommonName.c_str());
            SkImageEncoder::EncodeFile(newRecord->fRgbDiffPath.c_str(),
                                       diffData.fResult.rgbDiffBitmap,
                                       SkImageEncoder::kPNG_Type, 100);
            diffData.fResult.rgbDiffBitmap.reset();
            bitmapsToCreate.rgbDiff = false;
        }

        if (bitmapsToCreate.whiteDiff
                && SkImageDiffer::RESULT_CORRECT != diffData.fResult.result
                && !diffData.fResult.whiteDiffBitmap.empty()
                && !newRecord->fCommonName.isEmpty()) {
            newRecord->fWhiteDiffPath = SkOSPath::SkPathJoin(fWhiteDiffDir.c_str(),
                                                             newRecord->fCommonName.c_str());
            SkImageEncoder::EncodeFile(newRecord->fWhiteDiffPath.c_str(),
                                       diffData.fResult.whiteDiffBitmap,
                                       SkImageEncoder::kPNG_Type, 100);
            diffData.fResult.whiteDiffBitmap.reset();
            bitmapsToCreate.whiteDiff = false;
        }
    }
}

class SkThreadedDiff : public SkRunnable {
public:
    SkThreadedDiff() : fDiffContext(NULL) { }

    void setup(SkDiffContext* diffContext, const SkString& baselinePath, const SkString& testPath) {
        fDiffContext = diffContext;
        fBaselinePath = baselinePath;
        fTestPath = testPath;
    }

    virtual void run() SK_OVERRIDE {
        fDiffContext->addDiff(fBaselinePath.c_str(), fTestPath.c_str());
    }

private:
    SkDiffContext* fDiffContext;
    SkString fBaselinePath;
    SkString fTestPath;
};

void SkDiffContext::diffDirectories(const char baselinePath[], const char testPath[]) {
    // Get the files in the baseline, we will then look for those inside the test path
    SkTArray<SkString> baselineEntries;
    if (!get_directory(baselinePath, &baselineEntries)) {
        SkDebugf("Unable to open path \"%s\"\n", baselinePath);
        return;
    }

    SkThreadPool threadPool(fThreadCount);
    SkTArray<SkThreadedDiff> runnableDiffs;
    runnableDiffs.reset(baselineEntries.count());

    for (int x = 0; x < baselineEntries.count(); x++) {
        const char* baseFilename = baselineEntries[x].c_str();

        // Find the real location of each file to compare
        SkString baselineFile = SkOSPath::SkPathJoin(baselinePath, baseFilename);
        SkString testFile = SkOSPath::SkPathJoin(testPath, baseFilename);

        // Check that the test file exists and is a file
        if (sk_exists(testFile.c_str()) && !sk_isdir(testFile.c_str())) {
            // Queue up the comparison with the differ
            runnableDiffs[x].setup(this, baselineFile, testFile);
            threadPool.add(&runnableDiffs[x]);
        } else {
            SkDebugf("Baseline file \"%s\" has no corresponding test file\n", baselineFile.c_str());
        }
    }

    threadPool.wait();
}


void SkDiffContext::diffPatterns(const char baselinePattern[], const char testPattern[]) {
    // Get the files in the baseline and test patterns. Because they are in sorted order, it's easy
    // to find corresponding images by matching entry indices.

    SkTArray<SkString> baselineEntries;
    if (!glob_files(baselinePattern, &baselineEntries)) {
        SkDebugf("Unable to get pattern \"%s\"\n", baselinePattern);
        return;
    }

    SkTArray<SkString> testEntries;
    if (!glob_files(testPattern, &testEntries)) {
        SkDebugf("Unable to get pattern \"%s\"\n", testPattern);
        return;
    }

    if (baselineEntries.count() != testEntries.count()) {
        SkDebugf("Baseline and test patterns do not yield corresponding number of files\n");
        return;
    }

    SkThreadPool threadPool(fThreadCount);
    SkTArray<SkThreadedDiff> runnableDiffs;
    runnableDiffs.reset(baselineEntries.count());

    for (int x = 0; x < baselineEntries.count(); x++) {
        runnableDiffs[x].setup(this, baselineEntries[x], testEntries[x]);
        threadPool.add(&runnableDiffs[x]);
    }

    threadPool.wait();
}

void SkDiffContext::outputRecords(SkWStream& stream, bool useJSONP) {
    SkTLList<DiffRecord>::Iter iter(fRecords, SkTLList<DiffRecord>::Iter::kHead_IterStart);
    DiffRecord* currentRecord = iter.get();

    if (useJSONP) {
        stream.writeText("var SkPDiffRecords = {\n");
    } else {
        stream.writeText("{\n");
    }

    // TODO(djsollen): Would it be better to use the jsoncpp library to write out the JSON?
    // This manual approach is probably more efficient, but it sure is ugly.
    // See http://skbug.com/2713 ('make skpdiff use jsoncpp library to write out
    // JSON output, instead of manual writeText() calls?')
    stream.writeText("    \"records\": [\n");
    while (NULL != currentRecord) {
        stream.writeText("        {\n");

            SkString baselineAbsPath = get_absolute_path(currentRecord->fBaselinePath);
            SkString testAbsPath = get_absolute_path(currentRecord->fTestPath);

            stream.writeText("            \"commonName\": \"");
            stream.writeText(currentRecord->fCommonName.c_str());
            stream.writeText("\",\n");

            stream.writeText("            \"differencePath\": \"");
            stream.writeText(get_absolute_path(currentRecord->fAlphaMaskPath).c_str());
            stream.writeText("\",\n");

            stream.writeText("            \"rgbDiffPath\": \"");
            stream.writeText(get_absolute_path(currentRecord->fRgbDiffPath).c_str());
            stream.writeText("\",\n");

            stream.writeText("            \"whiteDiffPath\": \"");
            stream.writeText(get_absolute_path(currentRecord->fWhiteDiffPath).c_str());
            stream.writeText("\",\n");

            stream.writeText("            \"baselinePath\": \"");
            stream.writeText(baselineAbsPath.c_str());
            stream.writeText("\",\n");

            stream.writeText("            \"testPath\": \"");
            stream.writeText(testAbsPath.c_str());
            stream.writeText("\",\n");

            stream.writeText("            \"width\": ");
            stream.writeDecAsText(currentRecord->fSize.width());
            stream.writeText(",\n");
            stream.writeText("            \"height\": ");
            stream.writeDecAsText(currentRecord->fSize.height());
            stream.writeText(",\n");

            stream.writeText("            \"maxRedDiff\": ");
            stream.writeDecAsText(currentRecord->fMaxRedDiff);
            stream.writeText(",\n");
            stream.writeText("            \"maxGreenDiff\": ");
            stream.writeDecAsText(currentRecord->fMaxGreenDiff);
            stream.writeText(",\n");
            stream.writeText("            \"maxBlueDiff\": ");
            stream.writeDecAsText(currentRecord->fMaxBlueDiff);
            stream.writeText(",\n");

            stream.writeText("            \"diffs\": [\n");
            for (int diffIndex = 0; diffIndex < currentRecord->fDiffs.count(); diffIndex++) {
                DiffData& data = currentRecord->fDiffs[diffIndex];
                stream.writeText("                {\n");

                    stream.writeText("                    \"differName\": \"");
                    stream.writeText(data.fDiffName);
                    stream.writeText("\",\n");

                    stream.writeText("                    \"result\": ");
                    stream.writeScalarAsText((SkScalar)data.fResult.result);
                    stream.writeText(",\n");

                    stream.writeText("                    \"pointsOfInterest\": ");
                    stream.writeDecAsText(data.fResult.poiCount);
                    stream.writeText("\n");

                stream.writeText("                }");

                // JSON does not allow trailing commas
                if (diffIndex + 1 < currentRecord->fDiffs.count()) {
                    stream.writeText(",");
                }
                stream.writeText("                \n");
            }
            stream.writeText("            ]\n");

        stream.writeText("        }");

        currentRecord = iter.next();

        // JSON does not allow trailing commas
        if (NULL != currentRecord) {
            stream.writeText(",");
        }
        stream.writeText("\n");
    }
    stream.writeText("    ]\n");
    if (useJSONP) {
        stream.writeText("};\n");
    } else {
        stream.writeText("}\n");
    }
}

void SkDiffContext::outputCsv(SkWStream& stream) {
    SkTDict<int> columns(2);
    int cntColumns = 0;

    stream.writeText("key");

    SkTLList<DiffRecord>::Iter iter(fRecords, SkTLList<DiffRecord>::Iter::kHead_IterStart);
    DiffRecord* currentRecord = iter.get();

    // Write CSV header and create a dictionary of all columns.
    while (NULL != currentRecord) {
        for (int diffIndex = 0; diffIndex < currentRecord->fDiffs.count(); diffIndex++) {
            DiffData& data = currentRecord->fDiffs[diffIndex];
            if (!columns.find(data.fDiffName)) {
                columns.set(data.fDiffName, cntColumns);
                stream.writeText(", ");
                stream.writeText(data.fDiffName);
                cntColumns++;
            }
        }
        currentRecord = iter.next();
    }
    stream.writeText("\n");

    double values[100];
    SkASSERT(cntColumns < 100);  // Make the array larger, if we ever have so many diff types.

    SkTLList<DiffRecord>::Iter iter2(fRecords, SkTLList<DiffRecord>::Iter::kHead_IterStart);
    currentRecord = iter2.get();
    while (NULL != currentRecord) {
        for (int i = 0; i < cntColumns; i++) {
            values[i] = -1;
        }

        for (int diffIndex = 0; diffIndex < currentRecord->fDiffs.count(); diffIndex++) {
            DiffData& data = currentRecord->fDiffs[diffIndex];
            int index = -1;
            SkAssertResult(columns.find(data.fDiffName, &index));
            SkASSERT(index >= 0 && index < cntColumns);
            values[index] = data.fResult.result;
        }

        const char* filename = currentRecord->fBaselinePath.c_str() +
                strlen(currentRecord->fBaselinePath.c_str()) - 1;
        while (filename > currentRecord->fBaselinePath.c_str() && *(filename - 1) != '/') {
            filename--;
        }

        stream.writeText(filename);

        for (int i = 0; i < cntColumns; i++) {
            SkString str;
            str.printf(", %f", values[i]);
            stream.writeText(str.c_str());
        }
        stream.writeText("\n");

        currentRecord = iter2.next();
    }
}
