/*
 * Copyright (C) 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;

ScriptGroup::ScriptGroup(Context *rsc) : ObjectBase(rsc) {
}

ScriptGroup::~ScriptGroup() {
    if (mRSC->mHal.funcs.scriptgroup.destroy) {
        mRSC->mHal.funcs.scriptgroup.destroy(mRSC, this);
    }

    for (size_t ct=0; ct < mLinks.size(); ct++) {
        delete mLinks[ct];
    }
}

ScriptGroup::IO::IO(const ScriptKernelID *kid) {
    mKernel = kid;
}

ScriptGroup::Node::Node(Script *s) {
    mScript = s;
    mSeen = false;
    mOrder = 0;
}

ScriptGroup::Node * ScriptGroup::findNode(Script *s) const {
    //ALOGE("find %p   %i", s, (int)mNodes.size());
    for (size_t ct=0; ct < mNodes.size(); ct++) {
        Node *n = mNodes[ct];
        for (size_t ct2=0; ct2 < n->mKernels.size(); ct2++) {
            if (n->mKernels[ct2]->mScript == s) {
                return n;
            }
        }
    }
    return NULL;
}

bool ScriptGroup::calcOrderRecurse(Node *n, int depth) {
    n->mSeen = true;
    if (n->mOrder < depth) {
        n->mOrder = depth;
    }
    bool ret = true;
    for (size_t ct=0; ct < n->mOutputs.size(); ct++) {
        const Link *l = n->mOutputs[ct];
        Node *nt = NULL;
        if (l->mDstField.get()) {
            nt = findNode(l->mDstField->mScript);
        } else {
            nt = findNode(l->mDstKernel->mScript);
        }
        if (nt->mSeen) {
            return false;
        }
        ret &= calcOrderRecurse(nt, n->mOrder + 1);
    }
    return ret;
}

#if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
static int CompareNodeForSort(ScriptGroup::Node *const* lhs,
                              ScriptGroup::Node *const* rhs) {
    if (lhs[0]->mOrder > rhs[0]->mOrder) {
        return 1;
    }
    return 0;
}
#else
class NodeCompare {
public:
    bool operator() (const ScriptGroup::Node* lhs,
                     const ScriptGroup::Node* rhs) {
        if (lhs->mOrder > rhs->mOrder) {
            return true;
        }
        return false;
    }
};
#endif

bool ScriptGroup::calcOrder() {
    // Make nodes
    for (size_t ct=0; ct < mKernels.size(); ct++) {
        const ScriptKernelID *k = mKernels[ct].get();
        //ALOGE(" kernel %i, %p  s=%p", (int)ct, k, mKernels[ct]->mScript);
        Node *n = findNode(k->mScript);
        //ALOGE("    n = %p", n);
        if (n == NULL) {
            n = new Node(k->mScript);
            mNodes.add(n);
        }
        n->mKernels.add(k);
    }

    // add links
    //ALOGE("link count %i", (int)mLinks.size());
    for (size_t ct=0; ct < mLinks.size(); ct++) {
        Link *l = mLinks[ct];
        //ALOGE("link  %i %p", (int)ct, l);
        Node *n = findNode(l->mSource->mScript);
        //ALOGE("link n %p", n);
        n->mOutputs.add(l);

        if (l->mDstKernel.get()) {
            //ALOGE("l->mDstKernel.get() %p", l->mDstKernel.get());
            n = findNode(l->mDstKernel->mScript);
            //ALOGE("  n1 %p", n);
            n->mInputs.add(l);
        } else {
            n = findNode(l->mDstField->mScript);
            //ALOGE("  n2 %p", n);
            n->mInputs.add(l);
        }
    }

    //ALOGE("node count %i", (int)mNodes.size());
    // Order nodes
    bool ret = true;
    for (size_t ct=0; ct < mNodes.size(); ct++) {
        Node *n = mNodes[ct];
        if (n->mInputs.size() == 0) {
            for (size_t ct2=0; ct2 < mNodes.size(); ct2++) {
                mNodes[ct2]->mSeen = false;
            }
            ret &= calcOrderRecurse(n, 0);
        }
    }

    for (size_t ct=0; ct < mKernels.size(); ct++) {
        const ScriptKernelID *k = mKernels[ct].get();
        const Node *n = findNode(k->mScript);

        if (k->mHasKernelOutput) {
            bool found = false;
            for (size_t ct2=0; ct2 < n->mOutputs.size(); ct2++) {
                if (n->mOutputs[ct2]->mSource.get() == k) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                //ALOGE("add io out %p", k);
                mOutputs.add(new IO(k));
            }
        }

        if (k->mHasKernelInput) {
            bool found = false;
            for (size_t ct2=0; ct2 < n->mInputs.size(); ct2++) {
                if (n->mInputs[ct2]->mDstKernel.get() == k) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                //ALOGE("add io in %p", k);
                mInputs.add(new IO(k));
            }
        }
    }

    // sort
#if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
    mNodes.sort(&CompareNodeForSort);
#else
    std::sort(mNodes.begin(), mNodes.end(), NodeCompare());
#endif

    return ret;
}

ScriptGroup * ScriptGroup::create(Context *rsc,
                           ScriptKernelID ** kernels, size_t kernelsSize,
                           ScriptKernelID ** src, size_t srcSize,
                           ScriptKernelID ** dstK, size_t dstKSize,
                           ScriptFieldID  ** dstF, size_t dstFSize,
                           const Type ** type, size_t typeSize) {

    size_t kernelCount = kernelsSize / sizeof(ScriptKernelID *);
    size_t linkCount = typeSize / sizeof(Type *);

    //ALOGE("ScriptGroup::create kernels=%i  links=%i", (int)kernelCount, (int)linkCount);


    // Start by counting unique kernel sources

    ScriptGroup *sg = new ScriptGroup(rsc);

    sg->mKernels.reserve(kernelCount);
    for (size_t ct=0; ct < kernelCount; ct++) {
        sg->mKernels.add(kernels[ct]);
    }

    sg->mLinks.reserve(linkCount);
    for (size_t ct=0; ct < linkCount; ct++) {
        Link *l = new Link();
        l->mType = type[ct];
        l->mSource = src[ct];
        l->mDstField = dstF[ct];
        l->mDstKernel = dstK[ct];
        sg->mLinks.add(l);
    }

    sg->calcOrder();

    // allocate links
    for (size_t ct=0; ct < sg->mNodes.size(); ct++) {
        const Node *n = sg->mNodes[ct];
        for (size_t ct2=0; ct2 < n->mOutputs.size(); ct2++) {
            Link *l = n->mOutputs[ct2];
            if (l->mAlloc.get()) {
                continue;
            }
            const ScriptKernelID *k = l->mSource.get();

            Allocation * alloc = Allocation::createAllocation(rsc,
                    l->mType.get(), RS_ALLOCATION_USAGE_SCRIPT);
            l->mAlloc = alloc;

            for (size_t ct3=ct2+1; ct3 < n->mOutputs.size(); ct3++) {
                if (n->mOutputs[ct3]->mSource.get() == l->mSource.get()) {
                    n->mOutputs[ct3]->mAlloc = alloc;
                }
            }
        }
    }

    if (rsc->mHal.funcs.scriptgroup.init) {
        rsc->mHal.funcs.scriptgroup.init(rsc, sg);
    }
    sg->incUserRef();
    return sg;
}

void ScriptGroup::setInput(Context *rsc, ScriptKernelID *kid, Allocation *a) {
    for (size_t ct=0; ct < mInputs.size(); ct++) {
        if (mInputs[ct]->mKernel == kid) {
            mInputs[ct]->mAlloc = a;

            if (rsc->mHal.funcs.scriptgroup.setInput) {
                rsc->mHal.funcs.scriptgroup.setInput(rsc, this, kid, a);
            }
            return;
        }
    }
    rsAssert(!"ScriptGroup:setInput kid not found");
}

void ScriptGroup::setOutput(Context *rsc, ScriptKernelID *kid, Allocation *a) {
    for (size_t ct=0; ct < mOutputs.size(); ct++) {
        if (mOutputs[ct]->mKernel == kid) {
            mOutputs[ct]->mAlloc = a;

            if (rsc->mHal.funcs.scriptgroup.setOutput) {
                rsc->mHal.funcs.scriptgroup.setOutput(rsc, this, kid, a);
            }
            return;
        }
    }
    rsAssert(!"ScriptGroup:setOutput kid not found");
}

bool ScriptGroup::validateInputAndOutput(Context *rsc) {
    for(size_t i = 0; i < mInputs.size(); i++) {
        if (mInputs[i]->mAlloc.get() == NULL) {
            rsc->setError(RS_ERROR_BAD_VALUE, "ScriptGroup missing input.");
            return false;
        }
    }

    for(size_t i = 0; i < mOutputs.size(); i++) {
        if (mOutputs[i]->mAlloc.get() == NULL) {
            rsc->setError(RS_ERROR_BAD_VALUE, "ScriptGroup missing output.");
            return false;
        }
    }

    return true;
}

void ScriptGroup::execute(Context *rsc) {

    if (!validateInputAndOutput(rsc)) {
        return;
    }

    //ALOGE("ScriptGroup::execute");
    if (rsc->mHal.funcs.scriptgroup.execute) {
        rsc->mHal.funcs.scriptgroup.execute(rsc, this);
        return;
    }

    for (size_t ct=0; ct < mNodes.size(); ct++) {
        Node *n = mNodes[ct];
        //ALOGE("node %i, order %i, in %i out %i", (int)ct, n->mOrder, (int)n->mInputs.size(), (int)n->mOutputs.size());

        for (size_t ct2=0; ct2 < n->mKernels.size(); ct2++) {
            const ScriptKernelID *k = n->mKernels[ct2];
            Allocation *ain = NULL;
            Allocation *aout = NULL;

            for (size_t ct3=0; ct3 < n->mInputs.size(); ct3++) {
                if (n->mInputs[ct3]->mDstKernel.get() == k) {
                    ain = n->mInputs[ct3]->mAlloc.get();
                    //ALOGE(" link in %p", ain);
                }
            }
            for (size_t ct3=0; ct3 < mInputs.size(); ct3++) {
                if (mInputs[ct3]->mKernel == k) {
                    ain = mInputs[ct3]->mAlloc.get();
                    //ALOGE(" io in %p", ain);
                }
            }

            for (size_t ct3=0; ct3 < n->mOutputs.size(); ct3++) {
                if (n->mOutputs[ct3]->mSource.get() == k) {
                    aout = n->mOutputs[ct3]->mAlloc.get();
                    //ALOGE(" link out %p", aout);
                }
            }
            for (size_t ct3=0; ct3 < mOutputs.size(); ct3++) {
                if (mOutputs[ct3]->mKernel == k) {
                    aout = mOutputs[ct3]->mAlloc.get();
                    //ALOGE(" io out %p", aout);
                }
            }

            n->mScript->runForEach(rsc, k->mSlot, ain, aout, NULL, 0);
        }

    }

}

void ScriptGroup::serialize(Context *rsc, OStream *stream) const {
}

RsA3DClassID ScriptGroup::getClassId() const {
    return RS_A3D_CLASS_ID_SCRIPT_GROUP;
}

ScriptGroup::Link::Link() {
}

ScriptGroup::Link::~Link() {
}

namespace android {
namespace renderscript {


RsScriptGroup rsi_ScriptGroupCreate(Context *rsc,
                           RsScriptKernelID * kernels, size_t kernelsSize,
                           RsScriptKernelID * src, size_t srcSize,
                           RsScriptKernelID * dstK, size_t dstKSize,
                           RsScriptFieldID * dstF, size_t dstFSize,
                           const RsType * type, size_t typeSize) {


    return ScriptGroup::create(rsc,
                               (ScriptKernelID **) kernels, kernelsSize,
                               (ScriptKernelID **) src, srcSize,
                               (ScriptKernelID **) dstK, dstKSize,
                               (ScriptFieldID  **) dstF, dstFSize,
                               (const Type **) type, typeSize);
}


void rsi_ScriptGroupSetInput(Context *rsc, RsScriptGroup sg, RsScriptKernelID kid,
        RsAllocation alloc) {
    //ALOGE("rsi_ScriptGroupSetInput");
    ScriptGroup *s = (ScriptGroup *)sg;
    s->setInput(rsc, (ScriptKernelID *)kid, (Allocation *)alloc);
}

void rsi_ScriptGroupSetOutput(Context *rsc, RsScriptGroup sg, RsScriptKernelID kid,
        RsAllocation alloc) {
    //ALOGE("rsi_ScriptGroupSetOutput");
    ScriptGroup *s = (ScriptGroup *)sg;
    s->setOutput(rsc, (ScriptKernelID *)kid, (Allocation *)alloc);
}

void rsi_ScriptGroupExecute(Context *rsc, RsScriptGroup sg) {
    //ALOGE("rsi_ScriptGroupExecute");
    ScriptGroup *s = (ScriptGroup *)sg;
    s->execute(rsc);
}

}
}

