/*
 * 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 "skdiff_utils.h"
#include "SkBitmap.h"
#include "SkData.h"
#include "SkImageDecoder.h"
#include "SkImageEncoder.h"
#include "SkStream.h"
#include "SkTemplates.h"
#include "SkTypes.h"

bool are_buffers_equal(SkData* skdata1, SkData* skdata2) {
    if ((NULL == skdata1) || (NULL == skdata2)) {
        return false;
    }
    if (skdata1->size() != skdata2->size()) {
        return false;
    }
    return (0 == memcmp(skdata1->data(), skdata2->data(), skdata1->size()));
}

SkData* read_file(const char* file_path) {
    SkFILEStream fileStream(file_path);
    if (!fileStream.isValid()) {
        SkDebugf("WARNING: could not open file <%s> for reading\n", file_path);
        return NULL;
    }
    size_t bytesInFile = fileStream.getLength();
    size_t bytesLeftToRead = bytesInFile;

    void* bufferStart = sk_malloc_throw(bytesInFile);
    char* bufferPointer = (char*)bufferStart;
    while (bytesLeftToRead > 0) {
        size_t bytesReadThisTime = fileStream.read(bufferPointer, bytesLeftToRead);
        if (0 == bytesReadThisTime) {
            SkDebugf("WARNING: error reading from <%s>\n", file_path);
            sk_free(bufferStart);
            return NULL;
        }
        bytesLeftToRead -= bytesReadThisTime;
        bufferPointer += bytesReadThisTime;
    }
    return SkData::NewFromMalloc(bufferStart, bytesInFile);
}

bool get_bitmap(SkData* fileBits, DiffResource& resource, SkImageDecoder::Mode mode) {
    SkMemoryStream stream(fileBits->data(), fileBits->size());

    SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
    if (NULL == codec) {
        SkDebugf("ERROR: no codec found for <%s>\n", resource.fFullPath.c_str());
        resource.fStatus = DiffResource::kCouldNotDecode_Status;
        return false;
    }

    // In debug, the DLL will automatically be unloaded when this is deleted,
    // but that shouldn't be a problem in release mode.
    SkAutoTDelete<SkImageDecoder> ad(codec);

    stream.rewind();
    if (!codec->decode(&stream, &resource.fBitmap, kN32_SkColorType, mode)) {
        SkDebugf("ERROR: codec failed for basePath <%s>\n", resource.fFullPath.c_str());
        resource.fStatus = DiffResource::kCouldNotDecode_Status;
        return false;
    }

    resource.fStatus = DiffResource::kDecoded_Status;
    return true;
}

/** Thanks to PNG, we need to force all pixels 100% opaque. */
static void force_all_opaque(const SkBitmap& bitmap) {
   SkAutoLockPixels lock(bitmap);
   for (int y = 0; y < bitmap.height(); y++) {
       for (int x = 0; x < bitmap.width(); x++) {
           *bitmap.getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT);
       }
   }
}

bool write_bitmap(const SkString& path, const SkBitmap& bitmap) {
    SkBitmap copy;
    bitmap.copyTo(&copy, kN32_SkColorType);
    force_all_opaque(copy);
    return SkImageEncoder::EncodeFile(path.c_str(), copy,
                                      SkImageEncoder::kPNG_Type, 100);
}

/// Return a copy of the "input" string, within which we have replaced all instances
/// of oldSubstring with newSubstring.
///
/// TODO: If we like this, we should move it into the core SkString implementation,
/// adding more checks and ample test cases, and paying more attention to efficiency.
static SkString replace_all(const SkString &input,
                            const char oldSubstring[], const char newSubstring[]) {
    SkString output;
    const char *input_cstr = input.c_str();
    const char *first_char = input_cstr;
    const char *match_char;
    size_t oldSubstringLen = strlen(oldSubstring);
    while ((match_char = strstr(first_char, oldSubstring))) {
        output.append(first_char, (match_char - first_char));
        output.append(newSubstring);
        first_char = match_char + oldSubstringLen;
    }
    output.append(first_char);
    return output;
}

static SkString filename_to_derived_filename(const SkString& filename, const char *suffix) {
    SkString diffName (filename);
    const char* cstring = diffName.c_str();
    size_t dotOffset = strrchr(cstring, '.') - cstring;
    diffName.remove(dotOffset, diffName.size() - dotOffset);
    diffName.append(suffix);

    // In case we recursed into subdirectories, replace slashes with something else
    // so the diffs will all be written into a single flat directory.
    diffName = replace_all(diffName, PATH_DIV_STR, "_");
    return diffName;
}

SkString filename_to_diff_filename(const SkString& filename) {
    return filename_to_derived_filename(filename, "-diff.png");
}

SkString filename_to_white_filename(const SkString& filename) {
    return filename_to_derived_filename(filename, "-white.png");
}

void create_and_write_diff_image(DiffRecord* drp,
                                 DiffMetricProc dmp,
                                 const int colorThreshold,
                                 const SkString& outputDir,
                                 const SkString& filename) {
    const int w = drp->fBase.fBitmap.width();
    const int h = drp->fBase.fBitmap.height();

    if (w != drp->fComparison.fBitmap.width() || h != drp->fComparison.fBitmap.height()) {
        drp->fResult = DiffRecord::kDifferentSizes_Result;
    } else {
        drp->fDifference.fBitmap.allocN32Pixels(w, h);

        drp->fWhite.fBitmap.allocN32Pixels(w, h);

        SkASSERT(DiffRecord::kUnknown_Result == drp->fResult);
        compute_diff(drp, dmp, colorThreshold);
        SkASSERT(DiffRecord::kUnknown_Result != drp->fResult);
    }

    if (outputDir.isEmpty()) {
        drp->fDifference.fStatus = DiffResource::kUnspecified_Status;
        drp->fWhite.fStatus = DiffResource::kUnspecified_Status;

    } else {
        drp->fDifference.fFilename = filename_to_diff_filename(filename);
        drp->fDifference.fFullPath = outputDir;
        drp->fDifference.fFullPath.append(drp->fDifference.fFilename);
        drp->fDifference.fStatus = DiffResource::kSpecified_Status;

        drp->fWhite.fFilename = filename_to_white_filename(filename);
        drp->fWhite.fFullPath = outputDir;
        drp->fWhite.fFullPath.append(drp->fWhite.fFilename);
        drp->fWhite.fStatus = DiffResource::kSpecified_Status;

        if (DiffRecord::kDifferentPixels_Result == drp->fResult) {
            if (write_bitmap(drp->fDifference.fFullPath, drp->fDifference.fBitmap)) {
                drp->fDifference.fStatus = DiffResource::kExists_Status;
            } else {
                drp->fDifference.fStatus = DiffResource::kDoesNotExist_Status;
            }
            if (write_bitmap(drp->fWhite.fFullPath, drp->fWhite.fBitmap)) {
                drp->fWhite.fStatus = DiffResource::kExists_Status;
            } else {
                drp->fWhite.fStatus = DiffResource::kDoesNotExist_Status;
            }
        }
    }
}
