/*
 * 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 "skdiff.h"
#include "SkBitmap.h"
#include "SkColor.h"
#include "SkColorPriv.h"
#include "SkTypes.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;
}
