/*
 * soft_worker.cpp - soft worker implementation
 *
 *  Copyright (c) 2017 Intel Corporation
 *
 * 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.
 *
 * Author: Wind Yuan <feng.yuan@intel.com>
 */

#include "soft_worker.h"
#include "thread_pool.h"
#include "xcam_mutex.h"

namespace XCam {

class ItemSynch {
private:
    mutable std::atomic<uint32_t>  _remain_items;
    Mutex                          _mutex;
    XCamReturn                     _error;

public:
    ItemSynch (uint32_t items)
        : _remain_items(items), _error (XCAM_RETURN_NO_ERROR)
    {}
    void update_error (XCamReturn err) {
        SmartLock locker(_mutex);
        _error = err;
    }
    XCamReturn get_error () {
        SmartLock locker(_mutex);
        return _error;
    }
    uint32_t dec() {
        return --_remain_items;
    }

private:
    XCAM_DEAD_COPY (ItemSynch);
};

class WorkItem
    : public ThreadPool::UserData
{
public:
    WorkItem (
        const SmartPtr<SoftWorker> &worker,
        const SmartPtr<Worker::Arguments> &args,
        const WorkSize &item,
        SmartPtr<ItemSynch> &sync)
        : _worker (worker)
        , _args (args)
        , _item (item)
        , _sync (sync)
    {
    }
    virtual XCamReturn run ();
    virtual void done (XCamReturn err);


private:
    SmartPtr<SoftWorker>         _worker;
    SmartPtr<Worker::Arguments>  _args;
    WorkSize                     _item;
    SmartPtr<ItemSynch>          _sync;
};

XCamReturn
WorkItem::run ()
{
    XCamReturn ret = _sync->get_error();
    if (!xcam_ret_is_ok (ret))
        return ret;

    ret = _worker->work_impl (_args, _item);
    if (!xcam_ret_is_ok (ret))
        _sync->update_error (ret);

    return ret;
}

void
WorkItem::done (XCamReturn err)
{
    if (_sync->dec () == 0) {
        XCamReturn ret = _sync->get_error ();
        if (xcam_ret_is_ok (ret))
            ret = err;
        _worker->all_items_done (_args, ret);
    }
}

SoftWorker::SoftWorker (const char *name, const SmartPtr<Callback> &cb)
    : Worker (name, cb)
    , _global (1, 1, 1)
    , _local (1, 1, 1)
    , _work_unit (1, 1, 1)
{
}

SoftWorker::~SoftWorker ()
{
}

bool
SoftWorker::set_work_uint (uint32_t x, uint32_t y, uint32_t z)
{
    XCAM_FAIL_RETURN (
        ERROR, x && y && z, false,
        "SoftWorker(%s) set work unit failed(x:%d, y:%d, z:%d)",
        XCAM_STR (get_name ()), x, y, z);
    _work_unit.value[0] = x;
    _work_unit.value[1] = y;
    _work_unit.value[2] = z;
    return true;
}

bool
SoftWorker::set_threads (const SmartPtr<ThreadPool> &threads)
{
    XCAM_FAIL_RETURN (
        ERROR, !_threads.ptr (), false,
        "SoftWorker(%s) set threads failed, it's already set before.", XCAM_STR (get_name ()));
    _threads = threads;
    return true;
}

bool
SoftWorker::set_global_size (const WorkSize &size)
{
    XCAM_FAIL_RETURN (
        ERROR, size.value[0] && size.value[1] && size.value[2], false,
        "SoftWorker(%s) set global size(x:%d, y:%d, z:%d) failed.",
        XCAM_STR (get_name ()), size.value[0], size.value[1], size.value[2]);

    _global = size;
    return true;
}

bool
SoftWorker::set_local_size (const WorkSize &size)
{
    XCAM_FAIL_RETURN (
        ERROR, size.value[0] && size.value[1] && size.value[2], false,
        "SoftWorker(%s) set local size(x:%d, y:%d, z:%d) failed.",
        XCAM_STR (get_name ()), size.value[0], size.value[1], size.value[2]);

    _local = size;
    return true;
}

XCamReturn
SoftWorker::stop ()
{
    _threads->stop ();
    return XCAM_RETURN_NO_ERROR;
}

XCamReturn
SoftWorker::work (const SmartPtr<Worker::Arguments> &args)
{
    XCamReturn ret = XCAM_RETURN_NO_ERROR;

    XCAM_ASSERT (_local.value[0] * _local.value[1] * _local.value[2]);
    XCAM_ASSERT (_global.value[0] * _global.value[1] * _global.value[2]);

    WorkSize items;
    uint32_t max_items = 1;

    for (uint32_t i = 0; i < SOFT_MAX_DIM; ++i) {
        items.value[i] = xcam_ceil (_global.value[i],  _local.value[i]) / _local.value[i];
        max_items *= items.value[i];
    }

    XCAM_FAIL_RETURN (
        ERROR, max_items, XCAM_RETURN_ERROR_PARAM,
        "SoftWorker(%s) max item is zero. work failed.", XCAM_STR (get_name ()));

    if (max_items == 1) {
        ret = work_impl (args, WorkSize(0, 0, 0));
        status_check (args, ret);
        return ret;
    }

    if (!_threads.ptr ()) {
        char thr_name [XCAM_MAX_STR_SIZE];
        snprintf (thr_name, XCAM_MAX_STR_SIZE, "%s-thrs", XCAM_STR(get_name ()));
        _threads = new ThreadPool (thr_name);
        XCAM_ASSERT (_threads.ptr ());
        _threads->set_threads (max_items, max_items + 1); //extra thread to process all_items_done
        ret = _threads->start ();
        XCAM_FAIL_RETURN (
            ERROR, xcam_ret_is_ok (ret), ret,
            "SoftWorker(%s) work failed when starting threads", XCAM_STR(get_name()));
    }

    SmartPtr<ItemSynch> sync = new ItemSynch (max_items);
    for (uint32_t z = 0; z < items.value[2]; ++z)
        for (uint32_t y = 0; y < items.value[1]; ++y)
            for (uint32_t x = 0; x < items.value[0]; ++x)
            {
                SmartPtr<WorkItem> item = new WorkItem (this, args, WorkSize(x, y, z), sync);
                ret = _threads->queue (item);
                if (!xcam_ret_is_ok (ret)) {
                    //consider half queued but half failed
                    sync->update_error (ret);
                    //status_check (args, ret); // need it here?
                    XCAM_LOG_ERROR (
                        "SoftWorker(%s) queue work item(x:%d y: %d z:%d) failed",
                        XCAM_STR(get_name()), x, y, z);
                    return ret;
                }
            }

    return XCAM_RETURN_NO_ERROR;
}

void
SoftWorker::all_items_done (const SmartPtr<Arguments> &args, XCamReturn error)
{
    status_check (args, error);
}

WorkRange
SoftWorker::get_range (const WorkSize &item)
{
    WorkRange range;
    for (uint32_t i = 0; i < SOFT_MAX_DIM; ++i) {
        range.pos[i] = item.value[i] * _local.value[i];
        XCAM_ASSERT (range.pos[i] < _global.value[i]);
        if (range.pos[i] + _local.value[i] > _global.value[i])
            range.pos_len[i] = _global.value[i] - range.pos[i];
        else
            range.pos_len[i] = _local.value[i];
    }
    return range;
}

XCamReturn
SoftWorker::work_impl (const SmartPtr<Arguments> &args, const WorkSize &item)
{
    WorkRange range = get_range (item);
    return work_range (args, range);
}

XCamReturn
SoftWorker::work_range (const SmartPtr<Arguments> &args, const WorkRange &range)
{
    XCamReturn ret = XCAM_RETURN_NO_ERROR;
    WorkSize unit;
    memcpy(unit.value, range.pos, sizeof (unit.value));

    for (unit.value[2] = range.pos[2]; unit.value[2] < range.pos[2] + range.pos_len[2]; ++unit.value[2])
        for (unit.value[1] = range.pos[1]; unit.value[1] < range.pos[1] + range.pos_len[1]; ++unit.value[1])
            for (unit.value[0] = range.pos[0]; unit.value[0] < range.pos[0] + range.pos_len[0]; ++unit.value[0]) {
                ret = work_unit (args, unit);
                XCAM_FAIL_RETURN (
                    ERROR, xcam_ret_is_ok (ret), ret,
                    "SoftWorker(%s) work on pixel(x:%d y: %d z:%d) failed",
                    get_name (), unit.value[0], unit.value[1], unit.value[2]);
            }

    return ret;
}

XCamReturn
SoftWorker::work_unit (const SmartPtr<Arguments> &, const WorkSize &)
{
    XCAM_LOG_ERROR ("SoftWorker(%s) work_pixel was not derived. check code");
    return XCAM_RETURN_ERROR_PARAM;
}

};
