/*
 * 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 SkKTXFile_DEFINED
#define SkKTXFile_DEFINED

#include "SkData.h"
#include "SkTextureCompressor.h"
#include "SkTypes.h"
#include "SkTDArray.h"
#include "SkString.h"
#include "SkRefCnt.h"

class SkBitmap;
class SkStreamRewindable;
class SkWStream;

// KTX Image File
// ---
// KTX is a general texture data storage file format ratified by the Khronos Group. As an
// overview, a KTX file contains all of the appropriate values needed to fully specify a
// texture in an OpenGL application, including the use of compressed data.
//
// A full format specification can be found here:
// http://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/

class SkKTXFile {
public:
    // The ownership of the data remains with the caller. This class is intended
    // to be used as a logical wrapper around the data in order to properly
    // access the pixels.
    SkKTXFile(SkData* data) : fData(data), fSwapBytes(false) {
        data->ref();
        fValid = this->readKTXFile(fData->bytes(), fData->size());
    }

    bool valid() const { return fValid; }

    int width() const { return static_cast<int>(fHeader.fPixelWidth); }
    int height() const { return static_cast<int>(fHeader.fPixelHeight); }

    const uint8_t *pixelData(int mipmap = 0) const {
        SkASSERT(!this->valid() || mipmap < fPixelData.count());
        return this->valid() ? fPixelData[mipmap].data() : NULL;
    }

    // If the decoded KTX file has the following key, then it will
    // return the associated value. If not found, the empty string
    // is returned.
    SkString getValueForKey(const SkString& key) const;

    int numMipmaps() const { return static_cast<int>(fHeader.fNumberOfMipmapLevels); }

    bool isCompressedFormat(SkTextureCompressor::Format fmt) const;
    bool isRGBA8() const;
    bool isRGB8() const;

    static bool is_ktx(const uint8_t data[], size_t size);
    static bool is_ktx(SkStreamRewindable* stream);

    static bool WriteETC1ToKTX(SkWStream* stream, const uint8_t *etc1Data,
                               uint32_t width, uint32_t height);
    static bool WriteBitmapToKTX(SkWStream* stream, const SkBitmap& bitmap);
private:

    // The blob holding the file data.
    sk_sp<SkData> fData;

    // This header captures all of the data that describes the format
    // of the image data in a KTX file.
    struct Header {
        uint32_t fGLType;
        uint32_t fGLTypeSize;
        uint32_t fGLFormat;
        uint32_t fGLInternalFormat;
        uint32_t fGLBaseInternalFormat;
        uint32_t fPixelWidth;
        uint32_t fPixelHeight;
        uint32_t fPixelDepth;
        uint32_t fNumberOfArrayElements;
        uint32_t fNumberOfFaces;
        uint32_t fNumberOfMipmapLevels;
        uint32_t fBytesOfKeyValueData;

        Header() { memset(this, 0, sizeof(*this)); }
    } fHeader;

    // A Key Value pair stored in the KTX file. There may be
    // arbitrarily many of these.
    class KeyValue {
    public:
        KeyValue(size_t size) : fDataSz(size) { }
        bool readKeyAndValue(const uint8_t *data);
        size_t size() const { return fDataSz; }
        const SkString& key() const { return fKey; }
        const SkString& value() const { return fValue; }
        bool writeKeyAndValueForKTX(SkWStream* strm);
    private:
        const size_t fDataSz;
        SkString     fKey;
        SkString     fValue;
    };

    static KeyValue CreateKeyValue(const char *key, const char *value);

    // The pixel data for a single mipmap level in an image. Based on how
    // the rest of the data is stored, this may be compressed, a cubemap, etc.
    // The header will describe the format of this data.
    class PixelData {
    public:
        PixelData(const uint8_t *ptr, size_t sz) : fDataSz(sz), fDataPtr(ptr) { }
        const uint8_t *data() const { return fDataPtr; }
        size_t dataSize() const { return fDataSz; }
    private:
        const size_t fDataSz;
        const uint8_t *fDataPtr;
    };

    // This function is only called once from the constructor. It loads the data
    // and populates the appropriate fields of this class
    // (fKeyValuePairs, fPixelData, fSwapBytes)
    bool readKTXFile(const uint8_t *data, size_t dataLen);

    SkTArray<KeyValue> fKeyValuePairs;
    SkTDArray<PixelData> fPixelData;
    bool fValid;

    // If the endianness of the platform is different than the file,
    // then we need to do proper byte swapping.
    bool fSwapBytes;

    // Read an integer from a buffer, advance the buffer, and swap
    // bytes if fSwapBytes is set
    uint32_t readInt(const uint8_t** buf, size_t* bytesLeft) const;
};

#endif  // SkKTXFile_DEFINED
