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

#include "include/core/SkBitmap.h"
#include "include/core/SkColor.h"
#include "include/core/SkTypes.h"
#include "src/core/SkColorPriv.h"
#include "tools/skdiff/skdiff.h"

/*static*/ char const * const DiffRecord::ResultNames[DiffRecord::kResultCount] = {
    "EqualBits",
    "EqualPixels",
    "DifferentPixels",
    "DifferentSizes",
    "CouldNotCompare",
    "Unknown",
};

DiffRecord::Result DiffRecord::getResultByName(const char *name) {
    for (int result = 0; result < DiffRecord::kResultCount; ++result) {
        if (0 == strcmp(DiffRecord::ResultNames[result], name)) {
            return static_cast<DiffRecord::Result>(result);
        }
    }
    return DiffRecord::kResultCount;
}

static char const * const ResultDescriptions[DiffRecord::kResultCount] = {
    "contain exactly the same bits",
    "contain the same pixel values, but not the same bits",
    "have identical dimensions but some differing pixels",
    "have differing dimensions",
    "could not be compared",
    "not compared yet",
};

const char* DiffRecord::getResultDescription(DiffRecord::Result result) {
    return ResultDescriptions[result];
}

/*static*/ char const * const DiffResource::StatusNames[DiffResource::kStatusCount] = {
    "Decoded",
    "CouldNotDecode",

    "Read",
    "CouldNotRead",

    "Exists",
    "DoesNotExist",

    "Specified",
    "Unspecified",

    "Unknown",
};

DiffResource::Status DiffResource::getStatusByName(const char *name) {
    for (int status = 0; status < DiffResource::kStatusCount; ++status) {
        if (0 == strcmp(DiffResource::StatusNames[status], name)) {
            return static_cast<DiffResource::Status>(status);
        }
    }
    return DiffResource::kStatusCount;
}

static char const * const StatusDescriptions[DiffResource::kStatusCount] = {
    "decoded",
    "could not be decoded",

    "read",
    "could not be read",

    "found",
    "not found",

    "specified",
    "unspecified",

    "unknown",
};

const char* DiffResource::getStatusDescription(DiffResource::Status status) {
    return StatusDescriptions[status];
}

bool DiffResource::isStatusFailed(DiffResource::Status status) {
    return DiffResource::kCouldNotDecode_Status == status ||
           DiffResource::kCouldNotRead_Status == status ||
           DiffResource::kDoesNotExist_Status == status ||
           DiffResource::kUnspecified_Status == status ||
           DiffResource::kUnknown_Status == status;
}

bool DiffResource::getMatchingStatuses(char* selector, bool statuses[kStatusCount]) {
    if (!strcmp(selector, "any")) {
        for (int statusIndex = 0; statusIndex < kStatusCount; ++statusIndex) {
            statuses[statusIndex] = true;
        }
        return true;
    }

    for (int statusIndex = 0; statusIndex < kStatusCount; ++statusIndex) {
        statuses[statusIndex] = false;
    }

    static const char kDelimiterChar = ',';
    bool understood = true;
    while (true) {
        char* delimiterPtr = strchr(selector, kDelimiterChar);

        if (delimiterPtr) {
            *delimiterPtr = '\0';
        }

        if (!strcmp(selector, "failed")) {
            for (int statusIndex = 0; statusIndex < kStatusCount; ++statusIndex) {
                Status status = static_cast<Status>(statusIndex);
                statuses[statusIndex] |= isStatusFailed(status);
            }
        } else {
            Status status = getStatusByName(selector);
            if (status == kStatusCount) {
                understood = false;
            } else {
                statuses[status] = true;
            }
        }

        if (!delimiterPtr) {
            break;
        }

        *delimiterPtr = kDelimiterChar;
        selector = delimiterPtr + 1;
    }
    return understood;
}

static inline bool colors_match_thresholded(SkPMColor c0, SkPMColor c1, const int threshold) {
    int da = SkGetPackedA32(c0) - SkGetPackedA32(c1);
    int dr = SkGetPackedR32(c0) - SkGetPackedR32(c1);
    int dg = SkGetPackedG32(c0) - SkGetPackedG32(c1);
    int db = SkGetPackedB32(c0) - SkGetPackedB32(c1);

    return ((SkAbs32(da) <= threshold) &&
            (SkAbs32(dr) <= threshold) &&
            (SkAbs32(dg) <= threshold) &&
            (SkAbs32(db) <= threshold));
}

const SkPMColor PMCOLOR_WHITE = SkPreMultiplyColor(SK_ColorWHITE);
const SkPMColor PMCOLOR_BLACK = SkPreMultiplyColor(SK_ColorBLACK);

void compute_diff(DiffRecord* dr, DiffMetricProc diffFunction, const int colorThreshold) {
    const int w = dr->fComparison.fBitmap.width();
    const int h = dr->fComparison.fBitmap.height();
    if (w != dr->fBase.fBitmap.width() || h != dr->fBase.fBitmap.height()) {
        dr->fResult = DiffRecord::kDifferentSizes_Result;
        return;
    }

    int mismatchedPixels = 0;
    int totalMismatchA = 0;
    int totalMismatchR = 0;
    int totalMismatchG = 0;
    int totalMismatchB = 0;

    // Accumulate fractionally different pixels, then divide out
    // # of pixels at the end.
    dr->fWeightedFraction = 0;
    for (int y = 0; y < h; y++) {
        for (int x = 0; x < w; x++) {
            SkPMColor c0 = *dr->fBase.fBitmap.getAddr32(x, y);
            SkPMColor c1 = *dr->fComparison.fBitmap.getAddr32(x, y);
            SkPMColor outputDifference = diffFunction(c0, c1);
            uint32_t thisA = SkAbs32(SkGetPackedA32(c0) - SkGetPackedA32(c1));
            uint32_t thisR = SkAbs32(SkGetPackedR32(c0) - SkGetPackedR32(c1));
            uint32_t thisG = SkAbs32(SkGetPackedG32(c0) - SkGetPackedG32(c1));
            uint32_t thisB = SkAbs32(SkGetPackedB32(c0) - SkGetPackedB32(c1));
            totalMismatchA += thisA;
            totalMismatchR += thisR;
            totalMismatchG += thisG;
            totalMismatchB += thisB;
            // In HSV, value is defined as max RGB component.
            int value = MAX3(thisR, thisG, thisB);
            dr->fWeightedFraction += ((float) value) / 255;
            if (thisA > dr->fMaxMismatchA) {
                dr->fMaxMismatchA = thisA;
            }
            if (thisR > dr->fMaxMismatchR) {
                dr->fMaxMismatchR = thisR;
            }
            if (thisG > dr->fMaxMismatchG) {
                dr->fMaxMismatchG = thisG;
            }
            if (thisB > dr->fMaxMismatchB) {
                dr->fMaxMismatchB = thisB;
            }
            if (!colors_match_thresholded(c0, c1, colorThreshold)) {
                mismatchedPixels++;
                *dr->fDifference.fBitmap.getAddr32(x, y) = outputDifference;
                *dr->fWhite.fBitmap.getAddr32(x, y) = PMCOLOR_WHITE;
            } else {
                *dr->fDifference.fBitmap.getAddr32(x, y) = 0;
                *dr->fWhite.fBitmap.getAddr32(x, y) = PMCOLOR_BLACK;
            }
        }
    }
    if (0 == mismatchedPixels) {
        dr->fResult = DiffRecord::kEqualPixels_Result;
        return;
    }
    dr->fResult = DiffRecord::kDifferentPixels_Result;
    int pixelCount = w * h;
    dr->fFractionDifference = ((float) mismatchedPixels) / pixelCount;
    dr->fWeightedFraction /= pixelCount;
    dr->fTotalMismatchA = totalMismatchA;
    dr->fAverageMismatchA = ((float) totalMismatchA) / pixelCount;
    dr->fAverageMismatchR = ((float) totalMismatchR) / pixelCount;
    dr->fAverageMismatchG = ((float) totalMismatchG) / pixelCount;
    dr->fAverageMismatchB = ((float) totalMismatchB) / pixelCount;
}
