/*
 * 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 "gm_expectations.h"
#include "SkBitmapHasher.h"
#include "SkImageDecoder.h"

#define DEBUGFAIL_SEE_STDERR SkDEBUGFAIL("see stderr for message")

// See gm_json.py for descriptions of each of these JSON keys.
// These constants must be kept in sync with the ones in that Python file!
const static char kJsonKey_ActualResults[]   = "actual-results";
const static char kJsonKey_ActualResults_Failed[]        = "failed";
const static char kJsonKey_ActualResults_FailureIgnored[]= "failure-ignored";
const static char kJsonKey_ActualResults_NoComparison[]  = "no-comparison";
const static char kJsonKey_ActualResults_Succeeded[]     = "succeeded";
const static char kJsonKey_ExpectedResults[] = "expected-results";
const static char kJsonKey_ExpectedResults_AllowedDigests[] = "allowed-digests";
const static char kJsonKey_ExpectedResults_IgnoreFailure[]  = "ignore-failure";

// Types of result hashes we support in the JSON file.
const static char kJsonKey_Hashtype_Bitmap_64bitMD5[]  = "bitmap-64bitMD5";


namespace skiagm {
    SK_DEFINE_INST_COUNT(ExpectationsSource)

    void gm_fprintf(FILE *stream, const char format[], ...) {
        va_list args;
        va_start(args, format);
        fprintf(stream, "GM: ");
        vfprintf(stream, format, args);
        va_end(args);
    }

    Json::Value CreateJsonTree(Json::Value expectedResults,
                               Json::Value actualResultsFailed,
                               Json::Value actualResultsFailureIgnored,
                               Json::Value actualResultsNoComparison,
                               Json::Value actualResultsSucceeded) {
        Json::Value actualResults;
        actualResults[kJsonKey_ActualResults_Failed] = actualResultsFailed;
        actualResults[kJsonKey_ActualResults_FailureIgnored] = actualResultsFailureIgnored;
        actualResults[kJsonKey_ActualResults_NoComparison] = actualResultsNoComparison;
        actualResults[kJsonKey_ActualResults_Succeeded] = actualResultsSucceeded;
        Json::Value root;
        root[kJsonKey_ActualResults] = actualResults;
        root[kJsonKey_ExpectedResults] = expectedResults;
        return root;
    }


    // GmResultDigest class...

    GmResultDigest::GmResultDigest(const SkBitmap &bitmap) {
        fIsValid = SkBitmapHasher::ComputeDigest(bitmap, &fHashDigest);
    }

    GmResultDigest::GmResultDigest(const Json::Value &jsonTypeValuePair) {
        fIsValid = false;
        if (!jsonTypeValuePair.isArray()) {
            gm_fprintf(stderr, "found non-array json value when parsing GmResultDigest: %s\n",
                       jsonTypeValuePair.toStyledString().c_str());
            DEBUGFAIL_SEE_STDERR;
        } else if (2 != jsonTypeValuePair.size()) {
            gm_fprintf(stderr, "found json array with wrong size when parsing GmResultDigest: %s\n",
                       jsonTypeValuePair.toStyledString().c_str());
            DEBUGFAIL_SEE_STDERR;
        } else {
            // TODO(epoger): The current implementation assumes that the
            // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5
            Json::Value jsonHashValue = jsonTypeValuePair[1];
            if (!jsonHashValue.isIntegral()) {
                gm_fprintf(stderr,
                           "found non-integer jsonHashValue when parsing GmResultDigest: %s\n",
                           jsonTypeValuePair.toStyledString().c_str());
                DEBUGFAIL_SEE_STDERR;
            } else {
                fHashDigest = jsonHashValue.asUInt64();
                fIsValid = true;
            }
        }
    }

    bool GmResultDigest::isValid() const {
        return fIsValid;
    }

    bool GmResultDigest::equals(const GmResultDigest &other) const {
        // TODO(epoger): The current implementation assumes that this
        // and other are always of type kJsonKey_Hashtype_Bitmap_64bitMD5
        return (this->fIsValid && other.fIsValid && (this->fHashDigest == other.fHashDigest));
    }

    Json::Value GmResultDigest::asJsonTypeValuePair() const {
        // TODO(epoger): The current implementation assumes that the
        // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5
        Json::Value jsonTypeValuePair;
        if (fIsValid) {
            jsonTypeValuePair.append(Json::Value(kJsonKey_Hashtype_Bitmap_64bitMD5));
            jsonTypeValuePair.append(Json::UInt64(fHashDigest));
        } else {
            jsonTypeValuePair.append(Json::Value("INVALID"));
        }
        return jsonTypeValuePair;
    }

    SkString GmResultDigest::getHashType() const {
        // TODO(epoger): The current implementation assumes that the
        // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5
        return SkString(kJsonKey_Hashtype_Bitmap_64bitMD5);
    }

    SkString GmResultDigest::getDigestValue() const {
        // TODO(epoger): The current implementation assumes that the
        // result digest is always of type kJsonKey_Hashtype_Bitmap_64bitMD5
        SkString retval;
        retval.appendU64(fHashDigest);
        return retval;
    }


    // Expectations class...

    Expectations::Expectations(bool ignoreFailure) {
        fIgnoreFailure = ignoreFailure;
    }

    Expectations::Expectations(const SkBitmap& bitmap, bool ignoreFailure) {
        fBitmap = bitmap;
        fIgnoreFailure = ignoreFailure;
        fAllowedResultDigests.push_back(GmResultDigest(bitmap));
    }

    Expectations::Expectations(Json::Value jsonElement) {
        if (jsonElement.empty()) {
            fIgnoreFailure = kDefaultIgnoreFailure;
        } else {
            Json::Value ignoreFailure = jsonElement[kJsonKey_ExpectedResults_IgnoreFailure];
            if (ignoreFailure.isNull()) {
                fIgnoreFailure = kDefaultIgnoreFailure;
            } else if (!ignoreFailure.isBool()) {
                gm_fprintf(stderr, "found non-boolean json value"
                           " for key '%s' in element '%s'\n",
                           kJsonKey_ExpectedResults_IgnoreFailure,
                           jsonElement.toStyledString().c_str());
                DEBUGFAIL_SEE_STDERR;
                fIgnoreFailure = kDefaultIgnoreFailure;
            } else {
                fIgnoreFailure = ignoreFailure.asBool();
            }

            Json::Value allowedDigests = jsonElement[kJsonKey_ExpectedResults_AllowedDigests];
            if (allowedDigests.isNull()) {
                // ok, we'll just assume there aren't any AllowedDigests to compare against
            } else if (!allowedDigests.isArray()) {
                gm_fprintf(stderr, "found non-array json value"
                           " for key '%s' in element '%s'\n",
                           kJsonKey_ExpectedResults_AllowedDigests,
                           jsonElement.toStyledString().c_str());
                DEBUGFAIL_SEE_STDERR;
            } else {
                for (Json::ArrayIndex i=0; i<allowedDigests.size(); i++) {
                    fAllowedResultDigests.push_back(GmResultDigest(allowedDigests[i]));
                }
            }
        }
    }

    bool Expectations::match(GmResultDigest actualGmResultDigest) const {
        for (int i=0; i < this->fAllowedResultDigests.count(); i++) {
            GmResultDigest allowedResultDigest = this->fAllowedResultDigests[i];
            if (allowedResultDigest.equals(actualGmResultDigest)) {
                return true;
            }
        }
        return false;
    }

    Json::Value Expectations::asJsonValue() const {
        Json::Value allowedDigestArray;
        if (!this->fAllowedResultDigests.empty()) {
            for (int i=0; i < this->fAllowedResultDigests.count(); i++) {
                allowedDigestArray.append(this->fAllowedResultDigests[i].asJsonTypeValuePair());
            }
        }

        Json::Value jsonExpectations;
        jsonExpectations[kJsonKey_ExpectedResults_AllowedDigests] = allowedDigestArray;
        jsonExpectations[kJsonKey_ExpectedResults_IgnoreFailure]  = this->ignoreFailure();
        return jsonExpectations;
    }


    // IndividualImageExpectationsSource class...

    Expectations IndividualImageExpectationsSource::get(const char *testName) {
        SkString path = SkOSPath::SkPathJoin(fRootDir.c_str(), testName);
        SkBitmap referenceBitmap;
        bool decodedReferenceBitmap =
            SkImageDecoder::DecodeFile(path.c_str(), &referenceBitmap,
                                       SkBitmap::kARGB_8888_Config,
                                       SkImageDecoder::kDecodePixels_Mode,
                                       NULL);
        if (decodedReferenceBitmap) {
            return Expectations(referenceBitmap);
        } else {
            return Expectations();
        }
    }


    // JsonExpectationsSource class...

    JsonExpectationsSource::JsonExpectationsSource(const char *jsonPath) {
        Parse(jsonPath, &fJsonRoot);
        fJsonExpectedResults = fJsonRoot[kJsonKey_ExpectedResults];
    }

    Expectations JsonExpectationsSource::get(const char *testName) {
        return Expectations(fJsonExpectedResults[testName]);
    }

    /*static*/ SkData* JsonExpectationsSource::ReadIntoSkData(SkStream &stream, size_t maxBytes) {
        if (0 == maxBytes) {
            return SkData::NewEmpty();
        }
        char* bufStart = reinterpret_cast<char *>(sk_malloc_throw(maxBytes));
        char* bufPtr = bufStart;
        size_t bytesRemaining = maxBytes;
        while (bytesRemaining > 0) {
            size_t bytesReadThisTime = stream.read(bufPtr, bytesRemaining);
            if (0 == bytesReadThisTime) {
                break;
            }
            bytesRemaining -= bytesReadThisTime;
            bufPtr += bytesReadThisTime;
        }
        return SkData::NewFromMalloc(bufStart, maxBytes - bytesRemaining);
    }

    /*static*/ bool JsonExpectationsSource::Parse(const char *jsonPath, Json::Value *jsonRoot) {
        SkFILEStream inFile(jsonPath);
        if (!inFile.isValid()) {
            gm_fprintf(stderr, "unable to read JSON file %s\n", jsonPath);
            DEBUGFAIL_SEE_STDERR;
            return false;
        }

        SkAutoDataUnref dataRef(ReadFileIntoSkData(inFile));
        if (NULL == dataRef.get()) {
            gm_fprintf(stderr, "error reading JSON file %s\n", jsonPath);
            DEBUGFAIL_SEE_STDERR;
            return false;
        }

        const char *bytes = reinterpret_cast<const char *>(dataRef.get()->data());
        size_t size = dataRef.get()->size();
        Json::Reader reader;
        if (!reader.parse(bytes, bytes+size, *jsonRoot)) {
            gm_fprintf(stderr, "error parsing JSON file %s\n", jsonPath);
            DEBUGFAIL_SEE_STDERR;
            return false;
        }
        return true;
    }

}
