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

#include "include/core/SkColorSpace.h"
#include "include/core/SkImageInfo.h"

#include "include/c/sk_colorspace.h"
#include "include/c/sk_imageinfo.h"

#include <array>  // for std::size

const struct {
    sk_colortype_t  fC;
    SkColorType     fSK;
} gColorTypeMap[] = {
    { UNKNOWN_SK_COLORTYPE,     kUnknown_SkColorType    },
    { RGBA_8888_SK_COLORTYPE,   kRGBA_8888_SkColorType  },
    { BGRA_8888_SK_COLORTYPE,   kBGRA_8888_SkColorType  },
    { ALPHA_8_SK_COLORTYPE,     kAlpha_8_SkColorType    },
    { GRAY_8_SK_COLORTYPE,      kGray_8_SkColorType     },
    { RGBA_F16_SK_COLORTYPE,    kRGBA_F16_SkColorType   },
    { RGBA_F32_SK_COLORTYPE,    kRGBA_F32_SkColorType   },
};

const struct {
    sk_alphatype_t  fC;
    SkAlphaType     fSK;
} gAlphaTypeMap[] = {
    { OPAQUE_SK_ALPHATYPE,      kOpaque_SkAlphaType     },
    { PREMUL_SK_ALPHATYPE,      kPremul_SkAlphaType     },
    { UNPREMUL_SK_ALPHATYPE,    kUnpremul_SkAlphaType   },
};

static bool from_c_colortype(sk_colortype_t cCT, SkColorType* skCT) {
    for (size_t i = 0; i < std::size(gColorTypeMap); ++i) {
        if (gColorTypeMap[i].fC == cCT) {
            if (skCT) {
                *skCT = gColorTypeMap[i].fSK;
            }
            return true;
        }
    }
    return false;
}

static bool to_c_colortype(SkColorType skCT, sk_colortype_t* cCT) {
    for (size_t i = 0; i < std::size(gColorTypeMap); ++i) {
        if (gColorTypeMap[i].fSK == skCT) {
            if (cCT) {
                *cCT = gColorTypeMap[i].fC;
            }
            return true;
        }
    }
    return false;
}

static bool from_c_alphatype(sk_alphatype_t cAT, SkAlphaType* skAT) {
    for (size_t i = 0; i < std::size(gAlphaTypeMap); ++i) {
        if (gAlphaTypeMap[i].fC == cAT) {
            if (skAT) {
                *skAT = gAlphaTypeMap[i].fSK;
            }
            return true;
        }
    }
    return false;
}

static bool to_c_alphatype(SkAlphaType skAT, sk_alphatype_t* cAT) {
    for (size_t i = 0; i < std::size(gAlphaTypeMap); ++i) {
        if (gAlphaTypeMap[i].fSK == skAT) {
            if (cAT) {
                *cAT = gAlphaTypeMap[i].fC;
            }
            return true;
        }
    }
    return false;
}

const SkImageInfo* ToImageInfo(const sk_imageinfo_t* cinfo) {
    return reinterpret_cast<const SkImageInfo*>(cinfo);
}

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

sk_imageinfo_t* sk_imageinfo_new(int w, int h, sk_colortype_t cct, sk_alphatype_t cat,
                                 sk_colorspace_t* ccs) {
    SkColorType ct;
    SkAlphaType at;
    if (!from_c_colortype(cct, &ct) || !from_c_alphatype(cat, &at)) {
        return nullptr;
    }
    SkColorSpace* cs = (SkColorSpace*)ccs;

    SkImageInfo* info = new SkImageInfo(SkImageInfo::Make(w, h, ct, at, sk_ref_sp(cs)));
    return reinterpret_cast<sk_imageinfo_t*>(info);
}

void sk_imageinfo_delete(sk_imageinfo_t* cinfo) {
    delete ToImageInfo(cinfo);
}

int32_t sk_imageinfo_get_width(const sk_imageinfo_t* cinfo) {
    return ToImageInfo(cinfo)->width();
}

int32_t sk_imageinfo_get_height(const sk_imageinfo_t* cinfo) {
    return ToImageInfo(cinfo)->height();
}

sk_colortype_t sk_imageinfo_get_colortype(const sk_imageinfo_t* cinfo) {
    sk_colortype_t ct;
    return to_c_colortype(ToImageInfo(cinfo)->colorType(), &ct) ? ct : UNKNOWN_SK_COLORTYPE;
}

sk_alphatype_t sk_imageinfo_get_alphatype(const sk_imageinfo_t* cinfo) {
    sk_alphatype_t at;
    // odd that we return premul on failure...
    return to_c_alphatype(ToImageInfo(cinfo)->alphaType(), &at) ? at : PREMUL_SK_ALPHATYPE;
}

sk_colorspace_t* sk_imageinfo_get_colorspace(const sk_imageinfo_t* cinfo) {
    return reinterpret_cast<sk_colorspace_t*>(ToImageInfo(cinfo)->colorSpace());
}

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

sk_colorspace_t* sk_colorspace_new_srgb() {
    return reinterpret_cast<sk_colorspace_t*>(SkColorSpace::MakeSRGB().release());
}

void sk_colorspace_ref(sk_colorspace_t* cs) {
    SkSafeRef(reinterpret_cast<SkColorSpace*>(cs));
}

void sk_colorspace_unref(sk_colorspace_t* cs) {
    SkSafeUnref(reinterpret_cast<SkColorSpace*>(cs));
}

