/*
 * Copyright (C) 2017 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 "TunerSession.h"

#include "BroadcastRadio.h"

#include <android-base/logging.h>
#include <broadcastradio-utils-2x/Utils.h>

namespace android {
namespace hardware {
namespace broadcastradio {
namespace V2_0 {
namespace implementation {

using namespace std::chrono_literals;

using utils::tunesTo;

using std::lock_guard;
using std::move;
using std::mutex;
using std::sort;
using std::vector;

namespace delay {

static constexpr auto seek = 200ms;
static constexpr auto step = 100ms;
static constexpr auto tune = 150ms;
static constexpr auto list = 1s;

}  // namespace delay

TunerSession::TunerSession(BroadcastRadio& module, const sp<ITunerCallback>& callback)
    : mCallback(callback), mModule(module) {
    auto&& ranges = module.getAmFmConfig().ranges;
    if (ranges.size() > 0) {
        tuneInternalLocked(utils::make_selector_amfm(ranges[0].lowerBound));
    }
}

// makes ProgramInfo that points to no program
static ProgramInfo makeDummyProgramInfo(const ProgramSelector& selector) {
    ProgramInfo info = {};
    info.selector = selector;
    info.logicallyTunedTo = utils::make_identifier(
        IdentifierType::AMFM_FREQUENCY, utils::getId(selector, IdentifierType::AMFM_FREQUENCY));
    info.physicallyTunedTo = info.logicallyTunedTo;
    return info;
}

void TunerSession::tuneInternalLocked(const ProgramSelector& sel) {
    LOG(VERBOSE) << "tune (internal) to " << toString(sel);

    VirtualProgram virtualProgram;
    ProgramInfo programInfo;
    if (virtualRadio().getProgram(sel, virtualProgram)) {
        mCurrentProgram = virtualProgram.selector;
        programInfo = virtualProgram;
    } else {
        mCurrentProgram = sel;
        programInfo = makeDummyProgramInfo(sel);
    }
    mIsTuneCompleted = true;

    mCallback->onCurrentProgramInfoChanged(programInfo);
}

const BroadcastRadio& TunerSession::module() const {
    return mModule.get();
}

const VirtualRadio& TunerSession::virtualRadio() const {
    return module().mVirtualRadio;
}

Return<Result> TunerSession::tune(const ProgramSelector& sel) {
    LOG(DEBUG) << "tune to " << toString(sel);

    lock_guard<mutex> lk(mMut);
    if (mIsClosed) return Result::INVALID_STATE;

    if (!utils::isSupported(module().mProperties, sel)) {
        LOG(WARNING) << "selector not supported: " << toString(sel);
        return Result::NOT_SUPPORTED;
    }

    if (!utils::isValid(sel)) {
        LOG(ERROR) << "selector is not valid: " << toString(sel);
        return Result::INVALID_ARGUMENTS;
    }

    cancelLocked();

    mIsTuneCompleted = false;
    auto task = [this, sel]() {
        lock_guard<mutex> lk(mMut);
        tuneInternalLocked(sel);
    };
    mThread.schedule(task, delay::tune);

    return Result::OK;
}

Return<Result> TunerSession::scan(bool directionUp, bool skipSubChannel) {
    LOG(DEBUG) << "seek up=" << directionUp << " skipSubChannel=" << skipSubChannel;

    lock_guard<mutex> lk(mMut);
    if (mIsClosed) return Result::INVALID_STATE;

    cancelLocked();

    auto list = virtualRadio().getProgramList();

    if (list.empty()) {
        mIsTuneCompleted = false;
        auto task = [this]() {
            LOG(DEBUG) << "program list is empty, seek couldn't stop";

            mCallback->onTuneFailed(Result::TIMEOUT, {});
        };
        mThread.schedule(task, delay::seek);

        return Result::OK;
    }

    // Not optimal (O(sort) instead of O(n)), but not a big deal here;
    // also, it's likely that list is already sorted (so O(n) anyway).
    sort(list.begin(), list.end());
    auto current = mCurrentProgram;
    auto found = lower_bound(list.begin(), list.end(), VirtualProgram({current}));
    if (directionUp) {
        if (found < list.end() - 1) {
            if (tunesTo(current, found->selector)) found++;
        } else {
            found = list.begin();
        }
    } else {
        if (found > list.begin() && found != list.end()) {
            found--;
        } else {
            found = list.end() - 1;
        }
    }
    auto tuneTo = found->selector;

    mIsTuneCompleted = false;
    auto task = [this, tuneTo, directionUp]() {
        LOG(VERBOSE) << "executing seek up=" << directionUp;

        lock_guard<mutex> lk(mMut);
        tuneInternalLocked(tuneTo);
    };
    mThread.schedule(task, delay::seek);

    return Result::OK;
}

Return<Result> TunerSession::step(bool directionUp) {
    LOG(DEBUG) << "step up=" << directionUp;
    lock_guard<mutex> lk(mMut);
    if (mIsClosed) return Result::INVALID_STATE;

    cancelLocked();

    if (!utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY)) {
        LOG(WARNING) << "can't step in anything else than AM/FM";
        return Result::NOT_SUPPORTED;
    }

    auto stepTo = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY);
    auto range = getAmFmRangeLocked();
    if (!range) {
        LOG(ERROR) << "can't find current band";
        return Result::INTERNAL_ERROR;
    }

    if (directionUp) {
        stepTo += range->spacing;
    } else {
        stepTo -= range->spacing;
    }
    if (stepTo > range->upperBound) stepTo = range->lowerBound;
    if (stepTo < range->lowerBound) stepTo = range->upperBound;

    mIsTuneCompleted = false;
    auto task = [this, stepTo]() {
        LOG(VERBOSE) << "executing step to " << stepTo;

        lock_guard<mutex> lk(mMut);

        tuneInternalLocked(utils::make_selector_amfm(stepTo));
    };
    mThread.schedule(task, delay::step);

    return Result::OK;
}

void TunerSession::cancelLocked() {
    LOG(VERBOSE) << "cancelling current operations...";

    mThread.cancelAll();
    if (utils::getType(mCurrentProgram.primaryId) != IdentifierType::INVALID) {
        mIsTuneCompleted = true;
    }
}

Return<void> TunerSession::cancel() {
    lock_guard<mutex> lk(mMut);
    if (mIsClosed) return {};

    cancelLocked();

    return {};
}

Return<Result> TunerSession::startProgramListUpdates(const ProgramFilter& filter) {
    LOG(DEBUG) << "requested program list updates, filter=" << toString(filter);
    lock_guard<mutex> lk(mMut);
    if (mIsClosed) return Result::INVALID_STATE;

    auto list = virtualRadio().getProgramList();
    vector<VirtualProgram> filteredList;
    auto filterCb = [&filter](const VirtualProgram& program) {
        return utils::satisfies(filter, program.selector);
    };
    std::copy_if(list.begin(), list.end(), std::back_inserter(filteredList), filterCb);

    auto task = [this, filteredList]() {
        lock_guard<mutex> lk(mMut);

        ProgramListChunk chunk = {};
        chunk.purge = true;
        chunk.complete = true;
        chunk.modified = hidl_vec<ProgramInfo>(filteredList.begin(), filteredList.end());

        mCallback->onProgramListUpdated(chunk);
    };
    mThread.schedule(task, delay::list);

    return Result::OK;
}

Return<void> TunerSession::stopProgramListUpdates() {
    LOG(DEBUG) << "requested program list updates to stop";
    return {};
}

Return<void> TunerSession::isConfigFlagSet(ConfigFlag flag, isConfigFlagSet_cb _hidl_cb) {
    LOG(VERBOSE) << __func__ << " " << toString(flag);

    _hidl_cb(Result::NOT_SUPPORTED, false);
    return {};
}

Return<Result> TunerSession::setConfigFlag(ConfigFlag flag, bool value) {
    LOG(VERBOSE) << __func__ << " " << toString(flag) << " " << value;

    return Result::NOT_SUPPORTED;
}

Return<void> TunerSession::setParameters(const hidl_vec<VendorKeyValue>& /* parameters */,
                                         setParameters_cb _hidl_cb) {
    _hidl_cb({});
    return {};
}

Return<void> TunerSession::getParameters(const hidl_vec<hidl_string>& /* keys */,
                                         getParameters_cb _hidl_cb) {
    _hidl_cb({});
    return {};
}

Return<void> TunerSession::close() {
    LOG(DEBUG) << "closing session...";
    lock_guard<mutex> lk(mMut);
    if (mIsClosed) return {};

    mIsClosed = true;
    mThread.cancelAll();
    return {};
}

std::optional<AmFmBandRange> TunerSession::getAmFmRangeLocked() const {
    if (!mIsTuneCompleted) {
        LOG(WARNING) << "tune operation is in process";
        return {};
    }
    if (!utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY)) return {};

    auto freq = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY);
    for (auto&& range : module().getAmFmConfig().ranges) {
        if (range.lowerBound <= freq && range.upperBound >= freq) return range;
    }

    return {};
}

}  // namespace implementation
}  // namespace V2_0
}  // namespace broadcastradio
}  // namespace hardware
}  // namespace android
