/*
* Copyright 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "ShaderParser.h"

#include "GLcommon/GLutils.h"

#include <memory>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <vector>

ShaderParser::ShaderParser(GLenum type, bool coreProfile) : ObjectData(SHADER_DATA), m_type(type), m_coreProfile(coreProfile) {}

GenNameInfo ShaderParser::getGenNameInfo() const {
    switch (m_type) {
        case GL_VERTEX_SHADER:
            return GenNameInfo(ShaderProgramType::VERTEX_SHADER);
        case GL_FRAGMENT_SHADER:
            return GenNameInfo(ShaderProgramType::FRAGMENT_SHADER);
        case GL_COMPUTE_SHADER:
            return GenNameInfo(ShaderProgramType::COMPUTE_SHADER);
        default:
            assert(0);
            return GenNameInfo(NamedObjectType::SHADER_OR_PROGRAM);
    }
}

ShaderParser::ShaderParser(android::base::Stream* stream) : ObjectData(stream) {
    m_originalSrc = stream->getString();
    m_src = stream->getString();
    m_parsedSrc = stream->getString();
    m_parsedLines = (GLchar*)m_parsedSrc.c_str();
    m_compiledSrc = stream->getString();
    m_infoLog = stream->getString();
    size_t programSize = stream->getBe32();
    for (size_t program = 0; program < programSize; program++) {
        m_programs.insert(stream->getBe32());
    }
    m_type = stream->getBe32();
    m_compileStatus = stream->getByte();
    m_deleteStatus = stream->getByte();
    m_valid = stream->getByte();
    m_coreProfile = stream->getByte();
}

void ShaderParser::onSave(android::base::Stream* stream, unsigned int globalName) const {
    // The first byte is used to distinguish between program and shader object.
    // It will be loaded outside of this class
    stream->putByte(LOAD_SHADER);
    ObjectData::onSave(stream, globalName);
    stream->putString(m_originalSrc);
    stream->putString(m_src);
    stream->putString(m_parsedSrc);
    // do not snapshot m_parsedLines
    stream->putString(m_compiledSrc);
    stream->putString(m_infoLog);
    stream->putBe32(m_programs.size());
    for (const auto& program : m_programs) {
        stream->putBe32(program);
    }
    stream->putBe32(m_type);
    stream->putByte(m_compileStatus);
    stream->putByte(m_deleteStatus);
    stream->putByte(m_valid);
    stream->putByte(m_coreProfile);
}

void ShaderParser::restore(ObjectLocalName localName,
           const getGlobalName_t& getGlobalName) {
    ObjectData::restore(localName, getGlobalName);
    if (m_parsedSrc.empty()) return;
    int globalName = getGlobalName(NamedObjectType::SHADER_OR_PROGRAM,
            localName);
    if (isGles2Gles()) {
        const char* src = getOriginalSrc().c_str();
        GLEScontext::dispatcher().glShaderSource(globalName, 1, &src, NULL);
    } else {
        GLEScontext::dispatcher().glShaderSource(globalName, 1, parsedLines(), NULL);
    }
    if (m_compileStatus)
        GLEScontext::dispatcher().glCompileShader(globalName);
}

static const char kAlwaysInvalidShader[] =
    "When shader translation fails, passing an empty string to underlying GL "
    "may result in GL_COMPILE_STATUS == GL_TRUE and letting us link an "
    "invalid shader program, due to tripping the underlying GL's separable "
    "shader program capability."
    "This shader is meant to make the underlying GL agree that the shader is"
    "indeed invalid when translation fails.";

void ShaderParser::convertESSLToGLSL() {
    if (isGles2Gles()) {
        m_parsedSrc = m_originalSrc;
        return;
    }

    std::string translationLog;
    std::string parsedSource;

#if USE_ANGLE_SHADER_PARSER
    m_valid =
        ANGLEShaderParser::translate(
            m_coreProfile,
            m_originalSrc.c_str(),
            m_type,
            &translationLog,
            &parsedSource,
            &m_shaderLinkInfo);
#else
    m_valid = false;
#endif

    if (!m_valid) {
        m_infoLog = static_cast<const GLchar*>(translationLog.c_str());
        m_parsedSrc = kAlwaysInvalidShader;
    } else {
        m_parsedSrc = parsedSource;
    }
}

void ShaderParser::setSrc(GLsizei count, const GLchar* const* strings, const GLint* length){
    m_src.clear();
    for(int i = 0;i<count;i++){
        const size_t strLen =
                (length && length[i] >= 0) ? length[i] : strlen(strings[i]);
        m_src.append(strings[i], strings[i] + strLen);
    }
    // Store original source as some 'parsing' functions actually modify m_src.
    // Note: assign() call is a workaround for the reference-counting
    //  std::string in GCC's STL - we need a deep copy here.
    m_originalSrc.assign(m_src.c_str(), m_src.size());

    convertESSLToGLSL();
}

const GLchar** ShaderParser::parsedLines() {
      m_parsedLines = (GLchar*)m_parsedSrc.c_str();
      return const_cast<const GLchar**> (&m_parsedLines);
}

void ShaderParser::clear() {
    m_parsedLines = nullptr;
    std::string().swap(m_parsedSrc);
    std::string().swap(m_src);
}

const std::string& ShaderParser::getOriginalSrc() const {
    return m_originalSrc;
}

GLenum ShaderParser::getType() {
    return m_type;
}

void ShaderParser::setInfoLog(GLchar* infoLog) {
    assert(infoLog);
    std::unique_ptr<GLchar[]> infoLogDeleter(infoLog);
    m_infoLog.assign(infoLog);
}

bool ShaderParser::validShader() const {
    return m_valid;
}

static const GLchar glsles_invalid[] =
    { "ERROR: Valid GLSL but not GLSL ES" };

void ShaderParser::setInvalidInfoLog() {
    m_infoLog = glsles_invalid;
}

const GLchar* ShaderParser::getInfoLog() const {
    return m_infoLog.c_str();
}

void ShaderParser::setCompileStatus(bool val) {
    m_compileStatus = val;
    m_compiledSrc = m_parsedSrc.c_str();
}

void ShaderParser::attachProgram(GLuint program) {
    android::base::AutoLock lock(m_programsLock);
    m_programs.insert(program);
}

void ShaderParser::detachProgram(GLuint program) {
    android::base::AutoLock lock(m_programsLock);
    m_programs.erase(program);
}

bool ShaderParser::hasAttachedPrograms() const {
    android::base::AutoLock lock(m_programsLock);
    return m_programs.size() > 0;
}
