/*
 * 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 <time.h>

using namespace android;
using namespace android::renderscript;

Script::Script(Context *rsc) : ObjectBase(rsc) {
    memset(&mEnviroment, 0, sizeof(mEnviroment));
    memset(&mHal, 0, sizeof(mHal));

    mSlots = nullptr;
    mTypes = nullptr;
    mInitialized = false;
    mHasObjectSlots = false;
}

Script::~Script() {
    if (mSlots) {
        delete [] mSlots;
        mSlots = nullptr;
    }
    if (mTypes) {
        delete [] mTypes;
        mTypes = nullptr;
    }
}

void Script::setSlot(uint32_t slot, Allocation *a) {
    //ALOGE("setSlot %i %p", slot, a);
    if (slot >= mHal.info.exportedVariableCount) {
        ALOGE("Script::setSlot unable to set allocation, invalid slot index");
        return;
    }

    if (mRSC->hadFatalError()) return;

    mSlots[slot].set(a);
    mHasObjectSlots = true;
    mRSC->mHal.funcs.script.setGlobalBind(mRSC, this, slot, a);
}

void Script::setVar(uint32_t slot, const void *val, size_t len) {
    //ALOGE("setVar %i %p %i", slot, val, len);
    if (slot >= mHal.info.exportedVariableCount) {
        ALOGE("Script::setVar unable to set allocation, invalid slot index");
        return;
    }
    if (mRSC->hadFatalError()) return;

    mRSC->mHal.funcs.script.setGlobalVar(mRSC, this, slot, (void *)val, len);
}

void Script::getVar(uint32_t slot, const void *val, size_t len) {
    //ALOGE("getVar %i %p %i", slot, val, len);
    if (slot >= mHal.info.exportedVariableCount) {
        ALOGE("Script::getVar unable to set allocation, invalid slot index: "
              "%u >= %zu", slot, mHal.info.exportedVariableCount);
        return;
    }
    if (mRSC->hadFatalError()) return;

    mRSC->mHal.funcs.script.getGlobalVar(mRSC, this, slot, (void *)val, len);
}

void Script::setVar(uint32_t slot, const void *val, size_t len, Element *e,
                    const uint32_t *dims, size_t dimLen) {
    if (slot >= mHal.info.exportedVariableCount) {
        ALOGE("Script::setVar unable to set allocation, invalid slot index: "
              "%u >= %zu", slot, mHal.info.exportedVariableCount);
        return;
    }
    if (mRSC->hadFatalError()) return;

    mRSC->mHal.funcs.script.setGlobalVarWithElemDims(mRSC, this, slot,
            (void *)val, len, e, dims, dimLen);
}

void Script::setVarObj(uint32_t slot, ObjectBase *val) {
    //ALOGE("setVarObj %i %p", slot, val);
    if (slot >= mHal.info.exportedVariableCount) {
        ALOGE("Script::setVarObj unable to set allocation, invalid slot index: "
              "%u >= %zu", slot, mHal.info.exportedVariableCount);
        return;
    }
    if (mRSC->hadFatalError()) return;

    mHasObjectSlots = true;
    mRSC->mHal.funcs.script.setGlobalObj(mRSC, this, slot, val);
}

void Script::callUpdateCacheObject(const Context *rsc, void *dstObj) const {
    if (rsc->mHal.funcs.script.updateCachedObject != nullptr) {
        rsc->mHal.funcs.script.updateCachedObject(rsc, this, (rs_script *)dstObj);
    } else {
        *((const void **)dstObj) = this;
    }
}

bool Script::freeChildren() {
    incSysRef();
    mRSC->mHal.funcs.script.invokeFreeChildren(mRSC, this);
    return decSysRef();
}

ScriptKernelID::ScriptKernelID(Context *rsc, Script *s, int slot, int sig)
        : IDBase(rsc, s, slot) {
    mHasKernelInput = (sig & 1) != 0;
    mHasKernelOutput = (sig & 2) != 0;
}

RsA3DClassID ScriptKernelID::getClassId() const {
    return RS_A3D_CLASS_ID_SCRIPT_KERNEL_ID;
}

ScriptInvokeID::ScriptInvokeID(Context *rsc, Script *s, int slot)
    : IDBase(rsc, s, slot) {
}

RsA3DClassID ScriptInvokeID::getClassId() const {
    return RS_A3D_CLASS_ID_SCRIPT_INVOKE_ID;
}

ScriptFieldID::ScriptFieldID(Context *rsc, Script *s, int slot) :
    IDBase(rsc, s, slot) {
}

RsA3DClassID ScriptFieldID::getClassId() const {
    return RS_A3D_CLASS_ID_SCRIPT_FIELD_ID;
}


namespace android {
namespace renderscript {

RsScriptKernelID rsi_ScriptKernelIDCreate(Context *rsc, RsScript vs, int slot, int sig) {
    ScriptKernelID *kid = new ScriptKernelID(rsc, (Script *)vs, slot, sig);
    kid->incUserRef();
    return kid;
}

RsScriptInvokeID rsi_ScriptInvokeIDCreate(Context *rsc, RsScript vs, uint32_t slot) {
    ScriptInvokeID *iid = new ScriptInvokeID(rsc, (Script *)vs, slot);
    iid->incUserRef();
    return iid;
}

RsScriptFieldID rsi_ScriptFieldIDCreate(Context *rsc, RsScript vs, int slot) {
    ScriptFieldID *fid = new ScriptFieldID(rsc, (Script *)vs, slot);
    fid->incUserRef();
    return fid;
}

void rsi_ScriptBindAllocation(Context * rsc, RsScript vs, RsAllocation va, uint32_t slot) {
    Script *s = static_cast<Script *>(vs);
    Allocation *a = static_cast<Allocation *>(va);
    s->setSlot(slot, a);
}

void rsi_ScriptSetTimeZone(Context * rsc, RsScript vs, const char * timeZone, size_t length) {
    // We unfortunately need to make a new copy of the string, since it is
    // not nullptr-terminated. We then use setenv(), which properly handles
    // freeing/duplicating the actual string for the environment.
    char *tz = (char *) malloc(length + 1);
    if (!tz) {
        ALOGE("Couldn't allocate memory for timezone buffer");
        return;
    }
    strncpy(tz, timeZone, length);
    tz[length] = '\0';
    if (setenv("TZ", tz, 1) == 0) {
        tzset();
    } else {
        ALOGE("Error setting timezone");
    }
    free(tz);
}

void rsi_ScriptForEachMulti(Context *rsc, RsScript vs, uint32_t slot,
                            RsAllocation *vains, size_t inLen,
                            RsAllocation vaout, const void *params,
                            size_t paramLen, const RsScriptCall *sc,
                            size_t scLen) {

    Script      *s    = static_cast<Script *>(vs);
    Allocation **ains = (Allocation**)(vains);

    s->runForEach(rsc, slot,
                  const_cast<const Allocation **>(ains), inLen,
                  static_cast<Allocation *>(vaout), params, paramLen, sc);

}

void rsi_ScriptForEach(Context *rsc, RsScript vs, uint32_t slot,
                       RsAllocation vain, RsAllocation vaout,
                       const void *params, size_t paramLen,
                       const RsScriptCall *sc, size_t scLen) {

    if (vain == nullptr) {
        rsi_ScriptForEachMulti(rsc, vs, slot, nullptr, 0, vaout, params, paramLen,
                               sc, scLen);
    } else {
        RsAllocation ains[1] = {vain};

        rsi_ScriptForEachMulti(rsc, vs, slot, ains,
                               sizeof(ains) / sizeof(RsAllocation), vaout,
                               params, paramLen, sc, scLen);
    }
}

void rsi_ScriptInvoke(Context *rsc, RsScript vs, uint32_t slot) {
    Script *s = static_cast<Script *>(vs);
    s->Invoke(rsc, slot, nullptr, 0);
}


void rsi_ScriptInvokeData(Context *rsc, RsScript vs, uint32_t slot, void *data) {
    Script *s = static_cast<Script *>(vs);
    s->Invoke(rsc, slot, nullptr, 0);
}

void rsi_ScriptInvokeV(Context *rsc, RsScript vs, uint32_t slot, const void *data, size_t len) {
    Script *s = static_cast<Script *>(vs);
    s->Invoke(rsc, slot, data, len);
}

void rsi_ScriptSetVarI(Context *rsc, RsScript vs, uint32_t slot, int value) {
    Script *s = static_cast<Script *>(vs);
    s->setVar(slot, &value, sizeof(value));
}

void rsi_ScriptSetVarObj(Context *rsc, RsScript vs, uint32_t slot, RsObjectBase value) {
    Script *s = static_cast<Script *>(vs);
    ObjectBase *o = static_cast<ObjectBase *>(value);
    s->setVarObj(slot, o);
}

void rsi_ScriptSetVarJ(Context *rsc, RsScript vs, uint32_t slot, int64_t value) {
    Script *s = static_cast<Script *>(vs);
    s->setVar(slot, &value, sizeof(value));
}

void rsi_ScriptSetVarF(Context *rsc, RsScript vs, uint32_t slot, float value) {
    Script *s = static_cast<Script *>(vs);
    s->setVar(slot, &value, sizeof(value));
}

void rsi_ScriptSetVarD(Context *rsc, RsScript vs, uint32_t slot, double value) {
    Script *s = static_cast<Script *>(vs);
    s->setVar(slot, &value, sizeof(value));
}

void rsi_ScriptSetVarV(Context *rsc, RsScript vs, uint32_t slot, const void *data, size_t len) {
    Script *s = static_cast<Script *>(vs);
    s->setVar(slot, data, len);
}

void rsi_ScriptGetVarV(Context *rsc, RsScript vs, uint32_t slot, void *data, size_t len) {
    Script *s = static_cast<Script *>(vs);
    s->getVar(slot, data, len);
}

void rsi_ScriptSetVarVE(Context *rsc, RsScript vs, uint32_t slot,
                        const void *data, size_t len, RsElement ve,
                        const uint32_t *dims, size_t dimLen) {
    Script *s = static_cast<Script *>(vs);
    Element *e = static_cast<Element *>(ve);
    s->setVar(slot, data, len, e, dims, dimLen);
}

}
}
