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

#ifndef sk_tool_utils_DEFINED
#define sk_tool_utils_DEFINED

#include "SkColor.h"
#include "SkImageEncoder.h"
#include "SkImageInfo.h"
#include "SkPixelSerializer.h"
#include "SkRandom.h"
#include "SkTDArray.h"
#include "SkTypeface.h"

class SkBitmap;
class SkCanvas;
class SkPaint;
class SkPath;
class SkShader;
class SkTestFont;
class SkTextBlobBuilder;

namespace sk_tool_utils {

    const char* colortype_name(SkColorType);

    /**
     * Map opaque colors from 8888 to 565.
     */
    SkColor color_to_565(SkColor color);

    /**
     * Return a color emoji typeface if available.
     */
    sk_sp<SkTypeface> emoji_typeface();

    /**
     * If the platform supports color emoji, return sample text the emoji can render.
     */
    const char* emoji_sample_text();

    /**
     * If the platform supports color emoji, return the type (i.e. "CBDT", "SBIX", "").
     */
    const char* platform_os_emoji();

    /**
     * Return the platform name with the version number ("Mac10.9", "Win8", etc.) if available.
     */
    const char* platform_os_name();

    /**
     * Return the platform name without the version number ("Mac", "Win", etc.) if available.
     */
    SkString major_platform_os_name();

    /**
     * Return the platform extra config (e.g. "GDI") if available.
     */
    const char* platform_extra_config(const char* config);

    /**
     * Map serif, san-serif, and monospace to the platform-specific font name.
     */
    const char* platform_font_name(const char* name);

    /**
     * Sets the paint to use a platform-independent text renderer
     */
    void set_portable_typeface(SkPaint* paint, const char* name = nullptr,
                               SkFontStyle style = SkFontStyle());

    /**
     * Returns a platform-independent text renderer.
     */
    sk_sp<SkTypeface> create_portable_typeface(const char* name, SkFontStyle style);

    /** Call to clean up portable font references. */
    void release_portable_typefaces();

    /**
     *  Call canvas->writePixels() by using the pixels from bitmap, but with an info that claims
     *  the pixels are colorType + alphaType
     */
    void write_pixels(SkCanvas*, const SkBitmap&, int x, int y, SkColorType, SkAlphaType);

    // private to sk_tool_utils
    sk_sp<SkTypeface> create_font(const char* name, SkFontStyle);

    /** Returns a newly created CheckerboardShader. */
    sk_sp<SkShader> create_checkerboard_shader(SkColor c1, SkColor c2, int size);

    /** Draw a checkerboard pattern in the current canvas, restricted to
        the current clip, using SkXfermode::kSrc_Mode. */
    void draw_checkerboard(SkCanvas* canvas,
                           SkColor color1,
                           SkColor color2,
                           int checkSize);

    /** Make it easier to create a bitmap-based checkerboard */
    SkBitmap create_checkerboard_bitmap(int w, int h,
                                        SkColor c1, SkColor c2,
                                        int checkSize);

    /** A default checkerboard. */
    inline void draw_checkerboard(SkCanvas* canvas) {
        sk_tool_utils::draw_checkerboard(canvas, 0xFF999999, 0xFF666666, 8);
    }

    SkBitmap create_string_bitmap(int w, int h, SkColor c, int x, int y,
                                  int textSize, const char* str);

    // A helper for inserting a drawtext call into a SkTextBlobBuilder
    void add_to_text_blob(SkTextBlobBuilder* builder, const char* text, const SkPaint& origPaint,
                          SkScalar x, SkScalar y);

    void create_hemi_normal_map(SkBitmap* bm, const SkIRect& dst);

    void create_frustum_normal_map(SkBitmap* bm, const SkIRect& dst);

    void create_tetra_normal_map(SkBitmap* bm, const SkIRect& dst);

    void make_big_path(SkPath& path);

    // Return a blurred version of 'src'. This doesn't use a separable filter
    // so it is slow!
    SkBitmap slow_blur(const SkBitmap& src, float sigma);

    // A helper object to test the topological sorting code (TopoSortBench.cpp & TopoSortTest.cpp)
    class TopoTestNode {
    public:
        TopoTestNode(int id) : fID(id), fOutputPos(-1), fTempMark(false) { }

        void dependsOn(TopoTestNode* src) {
            *fDependencies.append() = src;
        }

        int id() const { return fID; }
        void reset() { fOutputPos = -1; }

        int outputPos() const { return fOutputPos; }

        // check that the topological sort is valid for this node
        bool check() {
            if (-1 == fOutputPos) {
                return false;
            }

            for (int i = 0; i < fDependencies.count(); ++i) {
                if (-1 == fDependencies[i]->outputPos()) {
                    return false;
                }
                // This node should've been output after all the nodes on which it depends
                if (fOutputPos < fDependencies[i]->outputPos()) {
                    return false;
                }
            }

            return true;
        }

        // The following 7 methods are needed by the topological sort
        static void SetTempMark(TopoTestNode* node) { node->fTempMark = true; }
        static void ResetTempMark(TopoTestNode* node) { node->fTempMark = false; }
        static bool IsTempMarked(TopoTestNode* node) { return node->fTempMark; }
        static void Output(TopoTestNode* node, int outputPos) {
            SkASSERT(-1 != outputPos);
            node->fOutputPos = outputPos;
        }
        static bool WasOutput(TopoTestNode* node) { return (-1 != node->fOutputPos); }
        static int NumDependencies(TopoTestNode* node) { return node->fDependencies.count(); }
        static TopoTestNode* Dependency(TopoTestNode* node, int index) {
            return node->fDependencies[index];
        }

        // Helper functions for TopoSortBench & TopoSortTest
        static void AllocNodes(SkTDArray<TopoTestNode*>* graph, int num) {
            graph->setReserve(num);

            for (int i = 0; i < num; ++i) {
                *graph->append() = new TopoTestNode(i);
            }
        }

        static void DeallocNodes(SkTDArray<TopoTestNode*>* graph) {
            for (int i = 0; i < graph->count(); ++i) {
                delete (*graph)[i];
            }
        }

        #ifdef SK_DEBUG
        static void Print(const SkTDArray<TopoTestNode*>& graph) {
            for (int i = 0; i < graph.count(); ++i) {
                SkDebugf("%d, ", graph[i]->id());
            }
            SkDebugf("\n");
        }
        #endif

        // randomize the array
        static void Shuffle(SkTDArray<TopoTestNode*>* graph, SkRandom* rand) {
            for (int i = graph->count()-1; i > 0; --i) {
                int swap = rand->nextU() % (i+1);

                TopoTestNode* tmp = (*graph)[i];
                (*graph)[i] = (*graph)[swap];
                (*graph)[swap] = tmp;
            }
        }

    private:
        int  fID;
        int  fOutputPos;
        bool fTempMark;

        SkTDArray<TopoTestNode*> fDependencies;
    };

}  // namespace sk_tool_utils

#endif  // sk_tool_utils_DEFINED
