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

#include "rsContext.h"
// TODO: Is this header needed here?
#include "rsScriptGroup2.h"

#include <algorithm>
#include <time.h>

using namespace android;
using namespace android::renderscript;

ScriptGroup::ScriptGroup(Context *rsc) : ScriptGroupBase(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];
    }

    for (auto input : mInputs) {
        input->mAlloc.clear();
    }

    for (auto output : mOutputs) {
        output->mAlloc.clear();
    }
}

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 nullptr;
}

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() == nullptr) {
            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() == nullptr) {
            rsc->setError(RS_ERROR_BAD_VALUE, "ScriptGroup missing output.");
            return false;
        }
    }

    return true;
}

void ScriptGroup::execute(Context *rsc) {
    if (!validateInputAndOutput(rsc)) {
        return;
    }

    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);
                }
            }

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

            } else {
                const Allocation *ains[1] = {ain};
                n->mScript->runForEach(rsc, k->mSlot, ains,
                                       sizeof(ains) / sizeof(RsAllocation),
                                       aout, NULL, 0);
            }
        }

    }

}

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) {
    ScriptGroupBase *s = (ScriptGroupBase *)sg;
    s->execute(rsc);
}

}
}
