/*
 * Copyright (C) 2009-2012 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 "rsContext.h"
#include "rsScriptC.h"

#if !defined(RS_COMPATIBILITY_LIB) && !defined(ANDROID_RS_SERIALIZE)
#include <bcinfo/BitcodeTranslator.h>
#include <bcinfo/BitcodeWrapper.h>
#endif

#if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
#include "utils/Timers.h"
#include "cutils/trace.h"
#endif

#include <sys/stat.h>

#include <sstream>
#include <string>

#ifdef USE_MINGW
/* Define the default path separator for the platform. */
#define OS_PATH_SEPARATOR     '\\'
#define OS_PATH_SEPARATOR_STR "\\"

#else /* not USE_MINGW */

/* Define the default path separator for the platform. */
#define OS_PATH_SEPARATOR     '/'
#define OS_PATH_SEPARATOR_STR "/"

#endif

using namespace android;
using namespace android::renderscript;

#define GET_TLS()  Context::ScriptTLSStruct * tls = \
    (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
    Context * rsc = tls->mContext; \
    ScriptC * sc = (ScriptC *) tls->mScript

ScriptC::ScriptC(Context *rsc) : Script(rsc) {
}

ScriptC::~ScriptC() {
    if (mInitialized) {
        mRSC->mHal.funcs.script.invokeFreeChildren(mRSC, this);
        mRSC->mHal.funcs.script.destroy(mRSC, this);
    }
}

#ifndef RS_COMPATIBILITY_LIB
bool ScriptC::createCacheDir(const char *cacheDir) {
    std::string currentDir;
    const std::string cacheDirString(cacheDir);

    struct stat statBuf;
    int statReturn = stat(cacheDir, &statBuf);
    if (!statReturn) {
        return true;
    }

    // Start from the beginning of the cacheDirString.
    int currPos = 0;

    // Reserve space in currentDir for the entire cacheDir path.
    currentDir.reserve(cacheDirString.length());

    while (currPos >= 0) {
        /*
         * The character at currPos should be a path separator.  We need to look
         * for the next one.
         */
        int nextPos = cacheDirString.find(OS_PATH_SEPARATOR_STR, currPos + 1);

        if (nextPos > 0) {
            // A new path separator has been found.
            currentDir += cacheDirString.substr(currPos, nextPos - currPos);
        } else {
            // There are no more path separators.
            currentDir += cacheDirString.substr(currPos);
        }

        currPos = nextPos;

        statReturn = stat(currentDir.c_str(), &statBuf);

        if (statReturn) {
            if (errno == ENOENT) {
                if (mkdir(currentDir.c_str(), S_IRUSR | S_IWUSR | S_IXUSR)) {
                    ALOGE("Couldn't create cache directory: %s",
                          currentDir.c_str());
                    ALOGE("Error: %s", strerror(errno));
                    return false;
                }
            } else {
                ALOGE("Stat error: %s", strerror(errno));
                return false;
            }
        }
    }
    return true;
}
#endif

void ScriptC::setupScript(Context *rsc) {
#ifndef RS_SERVER
    mEnviroment.mStartTimeMillis
                = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
#endif

    for (uint32_t ct=0; ct < mHal.info.exportedVariableCount; ct++) {
        if (mSlots[ct].get() && !mTypes[ct].get()) {
            mTypes[ct].set(mSlots[ct]->getType());
        }

        if (!mTypes[ct].get())
            continue;
        rsc->mHal.funcs.script.setGlobalBind(rsc, this, ct, mSlots[ct].get());
    }
}

void ScriptC::setupGLState(Context *rsc) {
#ifndef RS_COMPATIBILITY_LIB
    if (mEnviroment.mFragmentStore.get()) {
        rsc->setProgramStore(mEnviroment.mFragmentStore.get());
    }
    if (mEnviroment.mFragment.get()) {
        rsc->setProgramFragment(mEnviroment.mFragment.get());
    }
    if (mEnviroment.mVertex.get()) {
        rsc->setProgramVertex(mEnviroment.mVertex.get());
    }
    if (mEnviroment.mRaster.get()) {
        rsc->setProgramRaster(mEnviroment.mRaster.get());
    }
#endif
}

uint32_t ScriptC::run(Context *rsc) {
    if (mHal.info.root == nullptr) {
        rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
        return 0;
    }

    setupGLState(rsc);
    setupScript(rsc);

    uint32_t ret = 0;

    if (rsc->props.mLogScripts) {
        ALOGV("%p ScriptC::run invoking root,  ptr %p", rsc, mHal.info.root);
    }

    ret = rsc->mHal.funcs.script.invokeRoot(rsc, this);

    if (rsc->props.mLogScripts) {
        ALOGV("%p ScriptC::run invoking complete, ret=%i", rsc, ret);
    }

    return ret;
}


void ScriptC::runForEach(Context *rsc,
                         uint32_t slot,
                         const Allocation ** ains,
                         size_t inLen,
                         Allocation * aout,
                         const void * usr,
                         size_t usrBytes,
                         const RsScriptCall *sc) {
    // Make a copy of RsScriptCall and zero out extra fields that are absent
    // in API levels below 23.
    RsScriptCall sc_copy;
    if (sc != nullptr && getApiLevel() < 23) {
        memset(&sc_copy, 0, sizeof(sc_copy));
        memcpy(&sc_copy, sc, 7*4);
        sc = &sc_copy;
    }

    if (slot >= mHal.info.exportedForEachCount) {
        rsc->setError(RS_ERROR_BAD_SCRIPT,
                      "The forEach kernel index is out of bounds");
        return;
    }

    // Trace this function call.
    // To avoid overhead we only build the string if tracing is actually
    // enabled.
    std::stringstream ss;
    if (ATRACE_ENABLED()) {
        ss << "runForEach slot[" << slot << "]";
    }
    ATRACE_NAME(ss.str().c_str());

    if (mRSC->hadFatalError()) return;

    Context::PushState ps(rsc);

    setupGLState(rsc);
    setupScript(rsc);

    if (rsc->props.mLogScripts) {
        ALOGV("%p ScriptC::runForEach invoking slot %i, ptr %p", rsc, slot, this);
    }

    if (rsc->mHal.funcs.script.invokeForEachMulti != nullptr) {
        rsc->mHal.funcs.script.invokeForEachMulti(rsc, this, slot, ains, inLen,
                                                  aout, usr, usrBytes, sc);

    } else if (inLen == 1) {
        rsc->mHal.funcs.script.invokeForEach(rsc, this, slot, ains[0], aout,
                                             usr, usrBytes, sc);

    } else {
        rsc->setError(RS_ERROR_FATAL_DRIVER,
                      "Driver support for multi-input not present");
    }
}

void ScriptC::runReduce(Context *rsc, uint32_t slot,
                        const Allocation ** ains, size_t inLen,
                        Allocation *aout, const RsScriptCall *sc) {
  // TODO: Record the name of the kernel in the tracing information.
  ATRACE_CALL();

  if (slot >= mHal.info.exportedReduceCount) {
      rsc->setError(RS_ERROR_BAD_SCRIPT, "The general reduce kernel index is out of bounds");
      return;
  }
  if (mRSC->hadFatalError()) return;

  setupScript(rsc);

  if (rsc->props.mLogScripts) {
      ALOGV("%p ScriptC::runReduce invoking slot %i, ptr %p", rsc, slot, this);
  }

  rsc->mHal.funcs.script.invokeReduce(rsc, this, slot, ains, inLen, aout, sc);
}

void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, size_t len) {
    ATRACE_CALL();

    if (slot >= mHal.info.exportedFunctionCount) {
        rsc->setError(RS_ERROR_BAD_SCRIPT, "The invokable index is out of bounds");
        return;
    }
    if (mRSC->hadFatalError()) return;

    setupScript(rsc);

    if (rsc->props.mLogScripts) {
        ALOGV("%p ScriptC::Invoke invoking slot %i,  ptr %p", rsc, slot, this);
    }
    rsc->mHal.funcs.script.invokeFunction(rsc, this, slot, data, len);
}

static const bool kDebugBitcode = false;

#ifndef RS_COMPATIBILITY_LIB
#ifndef ANDROID_RS_SERIALIZE

static bool dumpBitcodeFile(const char *cacheDir, const char *resName,
                            const char *suffix, const uint8_t *bitcode,
                            size_t bitcodeLen) {
    std::string f(cacheDir);
    f.append("/");
    f.append(resName);
    f.append("#");
    f.append(suffix);
    f.append(".bc");

    if (!ScriptC::createCacheDir(cacheDir)) {
        return false;
    }

    FILE *fp = fopen(f.c_str(), "w");
    if (!fp) {
        ALOGE("Could not open %s", f.c_str());
        return false;
    }

    size_t nWritten = fwrite(bitcode, 1, bitcodeLen, fp);
    fclose(fp);
    if (nWritten != bitcodeLen) {
        ALOGE("Could not write %s", f.c_str());
        return false;
    }
    return true;
}

#endif  // !ANDROID_RS_SERIALIZE
#endif  // !RS_COMPATIBILITY_LIB


bool ScriptC::runCompiler(Context *rsc,
                          const char *resName,
                          const char *cacheDir,
                          const uint8_t *bitcode,
                          size_t bitcodeLen) {
    ATRACE_CALL();
    //ALOGE("runCompiler %p %p %p %p %p %i", rsc, this, resName, cacheDir, bitcode, bitcodeLen);
#ifndef RS_COMPATIBILITY_LIB
#ifndef ANDROID_RS_SERIALIZE
    uint32_t sdkVersion = 0;
    bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeLen);
    if (!bcWrapper.unwrap()) {
        ALOGE("Bitcode is not in proper container format (raw or wrapper)");
        return false;
    }

    if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) {
        sdkVersion = bcWrapper.getTargetAPI();
    }

    if (sdkVersion == 0) {
        // This signals that we didn't have a wrapper containing information
        // about the bitcode.
        sdkVersion = rsc->getTargetSdkVersion();
    }

    // Save off the sdkVersion, so that we can handle broken cases later.
    // Bug 19734267
    mApiLevel = sdkVersion;

    bcinfo::BitcodeTranslator BT((const char *)bitcode, bitcodeLen,
                                 sdkVersion);
    if (!BT.translate()) {
        ALOGE("Failed to translate bitcode from version: %u", sdkVersion);
        return false;
    }
    bitcode = (const uint8_t *) BT.getTranslatedBitcode();
    bitcodeLen = BT.getTranslatedBitcodeSize();

    if (kDebugBitcode) {
        if (!dumpBitcodeFile(cacheDir, resName, "after", bitcode, bitcodeLen)) {
            return false;
        }
    }


    // Set the optimization level of bcc to be the same as the
    // optimization level used to compile the bitcode.
    rsc->setOptLevel(bcWrapper.getOptimizationLevel());

#endif
    if (!cacheDir) {
        // MUST BE FIXED BEFORE ANYTHING USING C++ API IS RELEASED
        cacheDir = getenv("EXTERNAL_STORAGE");
        ALOGV("Cache dir changed to %s", cacheDir);
    }

    // ensure that cache dir exists
    if (cacheDir && !createCacheDir(cacheDir)) {
      return false;
    }
#endif

    if (!rsc->mHal.funcs.script.init(rsc, this, resName, cacheDir, bitcode, bitcodeLen, 0)) {
        return false;
    }

    mInitialized = true;
#ifndef RS_COMPATIBILITY_LIB
    mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
    mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
    mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore());
    mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
#endif

    rsc->mHal.funcs.script.invokeInit(rsc, this);

    for (size_t i=0; i < mHal.info.exportedPragmaCount; ++i) {
        const char * key = mHal.info.exportedPragmaKeyList[i];
        const char * value = mHal.info.exportedPragmaValueList[i];
        //ALOGE("pragma %s %s", keys[i], values[i]);
        if (!strcmp(key, "version")) {
            if (!strcmp(value, "1")) {
                continue;
            }
            ALOGE("Invalid version pragma value: %s\n", value);
            return false;
        }

#ifndef RS_COMPATIBILITY_LIB
        if (!strcmp(key, "stateVertex")) {
            if (!strcmp(value, "default")) {
                continue;
            }
            if (!strcmp(value, "parent")) {
                mEnviroment.mVertex.clear();
                continue;
            }
            ALOGE("Unrecognized value %s passed to stateVertex", value);
            return false;
        }

        if (!strcmp(key, "stateRaster")) {
            if (!strcmp(value, "default")) {
                continue;
            }
            if (!strcmp(value, "parent")) {
                mEnviroment.mRaster.clear();
                continue;
            }
            ALOGE("Unrecognized value %s passed to stateRaster", value);
            return false;
        }

        if (!strcmp(key, "stateFragment")) {
            if (!strcmp(value, "default")) {
                continue;
            }
            if (!strcmp(value, "parent")) {
                mEnviroment.mFragment.clear();
                continue;
            }
            ALOGE("Unrecognized value %s passed to stateFragment", value);
            return false;
        }

        if (!strcmp(key, "stateStore")) {
            if (!strcmp(value, "default")) {
                continue;
            }
            if (!strcmp(value, "parent")) {
                mEnviroment.mFragmentStore.clear();
                continue;
            }
            ALOGE("Unrecognized value %s passed to stateStore", value);
            return false;
        }
#endif

    }

    mSlots = new ObjectBaseRef<Allocation>[mHal.info.exportedVariableCount];
    mTypes = new ObjectBaseRef<const Type>[mHal.info.exportedVariableCount];

    return true;
}

namespace android {
namespace renderscript {

RsScript rsi_ScriptCCreate(Context *rsc,
                           const char *resName, size_t resName_length,
                           const char *cacheDir, size_t cacheDir_length,
                           const char *text, size_t text_length)
{
    ScriptC *s = new ScriptC(rsc);

    if (!s->runCompiler(rsc, resName, cacheDir, (uint8_t *)text, text_length)) {
        // Error during compile, destroy s and return null.
        ObjectBase::checkDelete(s);
        return nullptr;
    }

    s->incUserRef();
    return s;
}

}
}
