// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <fbl/alloc_checker.h>

#include <utility>

#include "debug-logging.h"
#include "usb-audio-path.h"

namespace audio {
namespace usb {

fbl::unique_ptr<AudioPath> AudioPath::Create(uint32_t unit_count) {
    fbl::AllocChecker ac;

    fbl::unique_ptr<fbl::RefPtr<AudioUnit>[]> units(new (&ac) fbl::RefPtr<AudioUnit>[unit_count]);
    if (!ac.check()) {
        GLOBAL_LOG(ERROR, "Failed to allocate %u units for AudioPath!", unit_count);
        return nullptr;
    }

    fbl::unique_ptr<AudioPath> ret(new (&ac) AudioPath(std::move(units), unit_count));
    if (!ac.check()) {
        GLOBAL_LOG(ERROR, "Failed to allocate AudioPath!");
        return nullptr;
    }

    return ret;
}

void AudioPath::AddUnit(uint32_t ndx, fbl::RefPtr<AudioUnit> unit) {
    ZX_DEBUG_ASSERT(ndx < unit_count_);
    ZX_DEBUG_ASSERT(unit != nullptr);
    units_[ndx] = std::move(unit);
}

zx_status_t AudioPath::Setup(const usb_protocol_t& proto) {
    // If setup is being called, we should have allocated a units_ array, and it
    // must be a minimum of 2 units long (the input and the output terminal).
    // All of its members must be non-null.  The first element in the array must
    // be an output terminal while the last element in the array must be an
    // input terminal.  Check all of this before proceeding.
    if ((units_ == nullptr) || (unit_count_ < 2)) {
        GLOBAL_LOG(ERROR, "Bad units array during %s (ptr %p, count %u)\n",
                   __PRETTY_FUNCTION__, units_.get(), unit_count_);
        return ZX_ERR_INTERNAL;
    }

    for (uint32_t i = 0; i < unit_count_; ++i) {
        if (units_[i] == nullptr) {
            GLOBAL_LOG(ERROR, "Empty unit slot %s (ndx %u)\n", __PRETTY_FUNCTION__, i);
            return ZX_ERR_INTERNAL;
        }
    }

    const auto& first_unit = *units_[0];
    if (first_unit.type() != AudioUnit::Type::OutputTerminal) {
        GLOBAL_LOG(ERROR,
                "First element of audio path must be an OutputTerminal, "
                "but a unit of type \"%s\" was discovered instead!\n",
                first_unit.type_name());
        return ZX_ERR_INTERNAL;
    }

    const auto& last_unit = *units_[unit_count_ - 1];
    if (last_unit.type() != AudioUnit::Type::InputTerminal) {
        GLOBAL_LOG(ERROR,
                "First element of audio path must be an InputTerminal, "
                "but a unit of type \"%s\" was discovered instead!\n",
                last_unit.type_name());
        return ZX_ERR_INTERNAL;
    }

    // Locate and stash a pointer to the terminal which serves as the bridge to
    // the host.  If this is the output terminal, then this path is an audio
    // input to the system, and vice-versa.  There should be exactly one stream
    // terminal in our path.
    //
    // If the stream terminal is an output terminal, then this is an audio input
    // path.  Otherwise it is an audio output path.
    const auto& out_term = static_cast<const OutputTerminal&>(first_unit);
    const auto& in_term = static_cast<const InputTerminal&>(last_unit);
    if (out_term.is_stream_terminal() == in_term.is_stream_terminal()) {
        GLOBAL_LOG(ERROR, "%s stream terminals found in audio path!\n",
                   out_term.is_stream_terminal() ? "Multiple" : "No");
        return ZX_ERR_INTERNAL;
    }

    if (out_term.is_stream_terminal()) {
        stream_terminal_.reset(&out_term);
        direction_ = Direction::Input;
    } else {
        stream_terminal_.reset(&in_term);
        direction_ = Direction::Output;
    }

    // Now walk the array of AudioUnits configuring our path.  In particular...
    //
    // ++ If we find SelectorUnits, make sure that they are configured to select
    //    the input which comes immediately before them.
    // ++ If we find MixerUnits, make sure that they are configured to pass
    //    through audio from the input which comes immediately before them.
    // ++ If we find FeatureUnits, make sure to stash a pointer to the first one
    //    we find.  This is where our volume control knob will be located (if
    //    any).
    //
    //    If any mixers or selectors we encounter are already in use, abort.  We
    //    don't know how to properly configure a device where multiple paths
    //    exist which share mixer/selector units.
    for (uint32_t i = 1; i < unit_count_ - 1; ++i) {
        const auto& unit = units_[i];

        // Skip anything which is not a selector, mixer, or feature unit.
        switch (unit->type()) {
            case AudioUnit::Type::SelectorUnit:
            case AudioUnit::Type::MixerUnit:
            case AudioUnit::Type::FeatureUnit:
                break;
            default:
                continue;
        }

        // Make sure the unit is not already in use.  We don't know how to share
        // any of these units with other paths.
        if (unit->in_use()) {
            GLOBAL_LOG(ERROR,
                       "AudioPath with in/out term ids = (%u/%u) encountered a %s "
                       "(id %u) which is already in use by another path.\n",
                       in_term.id(), out_term.id(), unit->type_name(), unit->id());
            return ZX_ERR_NOT_SUPPORTED;
        }

        if (unit->type() == AudioUnit::Type::SelectorUnit) {
            // Make certain that the upstream unit for this audio path is the
            // unit which has been selected.
            auto& selector_unit = static_cast<SelectorUnit&>(*unit);
            uint8_t upstream_id = static_cast<uint8_t>(units_[i + 1]->id());
            zx_status_t status = selector_unit.Select(proto, upstream_id);
            if (status != ZX_OK) {
                GLOBAL_LOG(ERROR,
                           "AudioPath with in/out term ids = (%u/%u) failed to set "
                           "selector id %u to source from upstream unit id %u (status %d)\n",
                           in_term.id(), out_term.id(), unit->id(), upstream_id, status);
                return status;
            }
        } else
        if (unit->type() == AudioUnit::Type::MixerUnit) {
            // TODO(johngro): (configure the mixer here)
        } else
        if (unit->type() == AudioUnit::Type::FeatureUnit) {
            // Right now, we don't know how to deal with a path which has
            // multiple volume knobs.
            if (feature_unit_ != nullptr) {
                GLOBAL_LOG(ERROR,
                           "AudioPath with in/out term ids = (%u/%u) encountered "
                           "a multiple feature units in the path.  We encountered "
                           "id %u, but already have id %u cached.\n",
                           in_term.id(), out_term.id(), unit->id(), feature_unit_->id());
                return ZX_ERR_NOT_SUPPORTED;
            }

            feature_unit_ = fbl::RefPtr<FeatureUnit>::Downcast(unit);
        }
    }

    // Things look good.  Flag all of the units in our path as being in use now.
    for (uint32_t i = 1; i < unit_count_ - 1; ++i) {
        units_[i]->set_in_use();
    }

    // If this path has a feature unit, then default the volume controls to 0dB
    // gain and unmuted.
    if (feature_unit_ != nullptr) {
        feature_unit_->SetMute(proto, false);
        feature_unit_->SetVol(proto, 0.0f);
        feature_unit_->SetAgc(proto, false);
    }

    return ZX_OK;
}

}  // namespace usb
}  // namespace audio

