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

#include "gm_knowledge.h"

#include <cfloat>
#include <cstdlib>
#include <fstream>
#include <mutex>
#include <sstream>
#include <string>
#include <vector>

#include "../../src/core/SkStreamPriv.h"
#include "../../src/core/SkTSort.h"
#include "SkBitmap.h"
#include "SkCodec.h"
#include "SkOSFile.h"
#include "SkOSPath.h"
#include "SkPngEncoder.h"
#include "SkStream.h"

#include "skqp_asset_manager.h"

#define IMAGES_DIRECTORY_PATH "images"
#define PATH_MAX_PNG "max.png"
#define PATH_MIN_PNG "min.png"
#define PATH_IMG_PNG "image.png"
#define PATH_ERR_PNG "errors.png"
#define PATH_REPORT  "report.html"
#define PATH_CSV     "out.csv"

#ifndef SK_SKQP_GLOBAL_ERROR_TOLERANCE
#define SK_SKQP_GLOBAL_ERROR_TOLERANCE 0
#endif

#ifndef SK_SKQP_BADNESS_TOLERANCE
#define SK_SKQP_BADNESS_TOLERANCE 100
#endif


////////////////////////////////////////////////////////////////////////////////

// TODO(halcanary) SkQP version 2 (for Q-release) should have a much cleaner mechanism.
static bool good_enough(const char* name, int64_t badnessMetric) {
    static const struct {
        const char* name;
        int64_t tolerance;
    } allowedBadnesses[] = {
        // These values are rounded up from failing tests reported by vendor.
        // The failures were perceptually good.
        { "circular_arcs_stroke_and_fill_round", 110   },
        { "circular_arcs_weird",                 12000 },
        { "drawTextRSXform",                     1000  },
        { "patheffect",                          260   },
        { "strokes_poly",                        1100  },
        { "stroketext",                          700   },
    };
    for (auto allowedBadness : allowedBadnesses) {
        if (0 == strcmp(allowedBadness.name, name)) {
            return badnessMetric < allowedBadness.tolerance;
        }
    }
    return badnessMetric < SK_SKQP_BADNESS_TOLERANCE;
}

static int get_error(uint32_t value, uint32_t value_max, uint32_t value_min) {
    int error = 0;
    for (int j : {0, 8, 16, 24}) {
        uint8_t    v = (value     >> j) & 0xFF,
                vmin = (value_min >> j) & 0xFF,
                vmax = (value_max >> j) & 0xFF;
        if (v > vmax) {
            error = std::max(v - vmax, error);
        } else if (v < vmin) {
            error = std::max(vmin - v, error);
        }
    }
    return std::max(0, error - SK_SKQP_GLOBAL_ERROR_TOLERANCE);
}

static int get_error_with_nearby(int x, int y, const SkPixmap& pm,
                                 const SkPixmap& pm_max, const SkPixmap& pm_min) {
    struct NearbyPixels {
        const int x, y, w, h;
        struct Iter {
            const int x, y, w, h;
            int8_t curr;
            SkIPoint operator*() const { return this->get(); }
            SkIPoint get() const {
                switch (curr) {
                    case 0: return {x - 1, y - 1};
                    case 1: return {x    , y - 1};
                    case 2: return {x + 1, y - 1};
                    case 3: return {x - 1, y    };
                    case 4: return {x + 1, y    };
                    case 5: return {x - 1, y + 1};
                    case 6: return {x    , y + 1};
                    case 7: return {x + 1, y + 1};
                    default: SkASSERT(false); return {0, 0};
                }
            }
            void skipBad() {
                while (curr < 8) {
                    SkIPoint p = this->get();
                    if (p.x() >= 0 && p.y() >= 0 && p.x() < w && p.y() < h) {
                        return;
                    }
                    ++curr;
                }
                curr = -1;
            }
            void operator++() {
                if (-1 == curr) { return; }
                ++curr;
                this->skipBad();
            }
            bool operator!=(const Iter& other) const { return curr != other.curr; }
        };
        Iter begin() const { Iter i{x, y, w, h, 0}; i.skipBad(); return i; }
        Iter end() const { return Iter{x, y, w, h, -1}; }
    };

    uint32_t c = *pm.addr32(x, y);
    int error = get_error(c, *pm_max.addr32(x, y), *pm_min.addr32(x, y));
    for (SkIPoint p : NearbyPixels{x, y, pm.width(), pm.height()}) {
        if (error == 0) {
            return 0;
        }
        error = SkTMin(error, get_error(
                    c, *pm_max.addr32(p.x(), p.y()), *pm_min.addr32(p.x(), p.y())));
    }
    return error;
}

static float set_error_code(gmkb::Error* error_out, gmkb::Error error) {
    SkASSERT(error != gmkb::Error::kNone);
    if (error_out) {
        *error_out = error;
    }
    return FLT_MAX;
}

static bool WritePixmapToFile(const SkPixmap& pixmap, const char* path) {
    SkFILEWStream wStream(path);
    SkPngEncoder::Options options;
    options.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore;
    return wStream.isValid() && SkPngEncoder::Encode(&wStream, pixmap, options);
}

constexpr SkColorType kColorType = kRGBA_8888_SkColorType;
constexpr SkAlphaType kAlphaType = kUnpremul_SkAlphaType;

static SkPixmap rgba8888_to_pixmap(const uint32_t* pixels, int width, int height) {
    SkImageInfo info = SkImageInfo::Make(width, height, kColorType, kAlphaType);
    return SkPixmap(info, pixels, width * sizeof(uint32_t));
}

static bool copy(skqp::AssetManager* mgr, const char* path, const char* dst) {
    if (mgr) {
        if (auto stream = mgr->open(path)) {
            SkFILEWStream wStream(dst);
            return wStream.isValid() && SkStreamCopy(&wStream, stream.get());
        }
    }
    return false;
}

static SkBitmap ReadPngRgba8888FromFile(skqp::AssetManager* assetManager, const char* path) {
    SkBitmap bitmap;
    if (auto codec = SkCodec::MakeFromStream(assetManager->open(path))) {
        SkISize size = codec->getInfo().dimensions();
        SkASSERT(!size.isEmpty());
        SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), kColorType, kAlphaType);
        bitmap.allocPixels(info);
        SkASSERT(bitmap.rowBytes() == (unsigned)bitmap.width() * sizeof(uint32_t));
        if (SkCodec::kSuccess != codec->getPixels(bitmap.pixmap())) {
            bitmap.reset();
        }
    }
    return bitmap;
}

namespace {
struct Run {
    SkString fBackend;
    SkString fGM;
    int fMaxerror;
    int fBadpixels;
};
}  // namespace

static std::vector<Run> gErrors;
static std::mutex gMutex;

static SkString make_path(const SkString& images_directory,
                          const char* backend,
                          const char* gm_name,
                          const char* thing) {
    auto path = SkStringPrintf("%s_%s_%s", backend, gm_name, thing);
    return SkOSPath::Join(images_directory.c_str(), path.c_str());
}


namespace gmkb {
float Check(const uint32_t* pixels,
            int width,
            int height,
            const char* name,
            const char* backend,
            skqp::AssetManager* assetManager,
            const char* report_directory_path,
            Error* error_out) {
    if (report_directory_path && report_directory_path[0]) {
        SkASSERT_RELEASE(sk_isdir(report_directory_path));
    }
    if (width <= 0 || height <= 0) {
        return set_error_code(error_out, Error::kBadInput);
    }
    constexpr char PATH_ROOT[] = "gmkb";
    SkString img_path = SkOSPath::Join(PATH_ROOT, name);
    SkString max_path = SkOSPath::Join(img_path.c_str(), PATH_MAX_PNG);
    SkString min_path = SkOSPath::Join(img_path.c_str(), PATH_MIN_PNG);
    SkBitmap max_image = ReadPngRgba8888FromFile(assetManager, max_path.c_str());
    SkBitmap min_image = ReadPngRgba8888FromFile(assetManager, min_path.c_str());
    if (max_image.isNull() || min_image.isNull()) {
        // No data.
        if (error_out) {
            *error_out = Error::kNone;
        }
        return 0;
    }
    if (max_image.width()  != min_image.width() ||
        max_image.height() != min_image.height())
    {
        return set_error_code(error_out, Error::kBadData);
    }
    if (max_image.width() != width || max_image.height() != height) {
        return set_error_code(error_out, Error::kBadInput);
    }

    int badness = 0;
    int badPixelCount = 0;
    SkPixmap pm(SkImageInfo::Make(width, height, kColorType, kAlphaType),
                pixels, width * sizeof(uint32_t));
    SkPixmap pm_max = max_image.pixmap();
    SkPixmap pm_min = min_image.pixmap();
    for (int y = 0; y < pm.height(); ++y) {
        for (int x = 0; x < pm.width(); ++x) {
            int error = get_error_with_nearby(x, y, pm, pm_max, pm_min) ;
            if (error > 0) {
                badness = SkTMax(error, badness);
                ++badPixelCount;
            }
        }
    }
    int64_t badnessMetric = badness * badPixelCount;
    if (good_enough(name, badnessMetric)) {
        std::lock_guard<std::mutex> lock(gMutex);
        gErrors.push_back(Run{SkString(backend), SkString(name), 0, 0});
        if (error_out) {
            *error_out = Error::kNone;
        }
        return 0;
    }
    if (report_directory_path && report_directory_path[0] != '\0') {
        SkString images_directory = SkOSPath::Join(report_directory_path, IMAGES_DIRECTORY_PATH);
        sk_mkdir(images_directory.c_str());

        SkString image_path   = make_path(images_directory, backend, name, PATH_IMG_PNG);
        SkString error_path   = make_path(images_directory, backend, name, PATH_ERR_PNG);
        SkString max_path_out = make_path(images_directory, backend, name, PATH_MAX_PNG);
        SkString min_path_out = make_path(images_directory, backend, name, PATH_MIN_PNG);

        SkAssertResult(WritePixmapToFile(rgba8888_to_pixmap(pixels, width, height),
                                         image_path.c_str()));

        SkBitmap errorBitmap;
        errorBitmap.allocPixels(SkImageInfo::Make(width, height, kColorType, kAlphaType));
        for (int y = 0; y < pm.height(); ++y) {
            for (int x = 0; x < pm.width(); ++x) {
                int error = get_error_with_nearby(x, y, pm, pm_max, pm_min);
                *errorBitmap.getAddr32(x, y) =
                         error > 0 ? 0xFF000000 + (unsigned)error : 0xFFFFFFFF;
            }
        }
        SkAssertResult(WritePixmapToFile(errorBitmap.pixmap(), error_path.c_str()));

        (void)copy(assetManager, max_path.c_str(), max_path_out.c_str());
        (void)copy(assetManager, min_path.c_str(), min_path_out.c_str());

        std::lock_guard<std::mutex> lock(gMutex);
        gErrors.push_back(Run{SkString(backend), SkString(name), badness, badPixelCount});
    }
    if (error_out) {
        *error_out = Error::kNone;
    }
    return (float)badnessMetric;
}

static constexpr char kDocHead[] =
    "<!doctype html>\n"
    "<html lang=\"en\">\n"
    "<head>\n"
    "<meta charset=\"UTF-8\">\n"
    "<title>SkQP Report</title>\n"
    "<style>\n"
    "img { max-width:48%; border:1px green solid;\n"
    "      image-rendering: pixelated;\n"
    "      background-image:url('data:image/png;base64,iVBORw0KGgoA"
    "AAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAAXNSR0IArs4c6QAAAAJiS0dEAP+H"
    "j8y/AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAB3RJTUUH3gUBEi4DGRAQYgAAAB1J"
    "REFUGNNjfMoAAVJQmokBDdBHgPE/lPFsYN0BABdaAwN6tehMAAAAAElFTkSuQmCC"
    "'); }\n"
    "</style>\n"
    "<script>\n"
    "function ce(t) { return document.createElement(t); }\n"
    "function ct(n) { return document.createTextNode(n); }\n"
    "function ac(u,v) { return u.appendChild(v); }\n"
    "function br(u) { ac(u, ce(\"br\")); }\n"
    "function ma(s, c) { var a = ce(\"a\"); a.href = s; ac(a, c); return a; }\n"
    "function f(backend, gm, e1, e2) {\n"
    "  var b = ce(\"div\");\n"
    "  var x = ce(\"h2\");\n"
    "  var t = backend + \"_\" + gm;\n"
    "  ac(x, ct(t));\n"
    "  ac(b, x);\n"
    "  ac(b, ct(\"backend: \" + backend));\n"
    "  br(b);\n"
    "  ac(b, ct(\"gm name: \" + gm));\n"
    "  br(b);\n"
    "  ac(b, ct(\"maximum error: \" + e1));\n"
    "  br(b);\n"
    "  ac(b, ct(\"bad pixel counts: \" + e2));\n"
    "  br(b);\n"
    "  var q = \"" IMAGES_DIRECTORY_PATH "/\" + backend + \"_\" + gm + \"_\";\n"
    "  var i = ce(\"img\");\n"
    "  i.src = q + \"" PATH_IMG_PNG "\";\n"
    "  i.alt = \"img\";\n"
    "  ac(b, ma(i.src, i));\n"
    "  i = ce(\"img\");\n"
    "  i.src = q + \"" PATH_ERR_PNG "\";\n"
    "  i.alt = \"err\";\n"
    "  ac(b, ma(i.src, i));\n"
    "  br(b);\n"
    "  ac(b, ct(\"Expectation: \"));\n"
    "  ac(b, ma(q + \"" PATH_MAX_PNG "\", ct(\"max\")));\n"
    "  ac(b, ct(\" | \"));\n"
    "  ac(b, ma(q + \"" PATH_MIN_PNG "\", ct(\"min\")));\n"
    "  ac(b, ce(\"hr\"));\n"
    "  b.id = backend + \":\" + gm;\n"
    "  ac(document.body, b);\n"
    "  l = ce(\"li\");\n"
    "  ac(l, ct(\"[\" + e1 + \"] \"));\n"
    "  ac(l, ma(\"#\" + backend +\":\"+ gm , ct(t)));\n"
    "  ac(document.getElementById(\"toc\"), l);\n"
    "}\n"
    "function main() {\n";

static constexpr char kDocMiddle[] =
    "}\n"
    "</script>\n"
    "</head>\n"
    "<body onload=\"main()\">\n"
    "<h1>SkQP Report</h1>\n";

static constexpr char kDocTail[] =
    "<ul id=\"toc\"></ul>\n"
    "<hr>\n"
    "<p>Left image: test result<br>\n"
    "Right image: errors (white = no error, black = smallest error, red = biggest error)</p>\n"
    "<hr>\n"
    "</body>\n"
    "</html>\n";

static void write(SkWStream* wStream, const SkString& text) {
    wStream->write(text.c_str(), text.size());
}

enum class Backend {
    kUnknown,
    kGLES,
    kVulkan,
};

static Backend get_backend(const SkString& s) {
    if (s.equals("gles")) {
        return Backend::kGLES;
    } else if (s.equals("vk")) {
        return Backend::kVulkan;
    }
    return Backend::kUnknown;
}


bool MakeReport(const char* report_directory_path) {
    int glesErrorCount = 0, vkErrorCount = 0, gles = 0, vk = 0;

    SkASSERT_RELEASE(sk_isdir(report_directory_path));
    std::lock_guard<std::mutex> lock(gMutex);
    SkFILEWStream csvOut(SkOSPath::Join(report_directory_path, PATH_CSV).c_str());
    SkFILEWStream htmOut(SkOSPath::Join(report_directory_path, PATH_REPORT).c_str());
    SkASSERT_RELEASE(csvOut.isValid());
    if (!csvOut.isValid() || !htmOut.isValid()) {
        return false;
    }
    htmOut.writeText(kDocHead);
    for (const Run& run : gErrors) {
        auto backend = get_backend(run.fBackend);
        switch (backend) {
            case Backend::kGLES: ++gles; break;
            case Backend::kVulkan: ++vk; break;
            default: break;
        }
        write(&csvOut, SkStringPrintf("\"%s\",\"%s\",%d,%d\n",
                                      run.fBackend.c_str(), run.fGM.c_str(),
                                      run.fMaxerror, run.fBadpixels));
        if (run.fMaxerror == 0 && run.fBadpixels == 0) {
            continue;
        }
        write(&htmOut, SkStringPrintf("  f(\"%s\", \"%s\", %d, %d);\n",
                                      run.fBackend.c_str(), run.fGM.c_str(),
                                      run.fMaxerror, run.fBadpixels));
        switch (backend) {
            case Backend::kGLES: ++glesErrorCount; break;
            case Backend::kVulkan: ++vkErrorCount; break;
            default: break;
        }
    }
    htmOut.writeText(kDocMiddle);
    write(&htmOut, SkStringPrintf("<p>gles errors: %d (of %d)</br>\n"
                                  "vk errors: %d (of %d)</p>\n",
                                  glesErrorCount, gles, vkErrorCount, vk));
    htmOut.writeText(kDocTail);
    return true;
}
}  // namespace gmkb
