#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (C) 2018 Takashi Sakamoto

from hinawa_utils.misc.cli_kit import CliKit
from hinawa_utils.fireface.ff_unit import FFUnit


def handle_status(unit, args):
    print('Model name: {0}'.format(unit.get_model_name()))

    print('Current configuration:')
    for target in unit.get_single_option_labels():
        print('  {0}'.format(target))
        for item in unit.get_single_option_item_labels(target):
            print('    {0}: {1}'.format(
                item, unit.get_single_option(target, item)))
    for target in unit.get_multiple_option_labels():
        print('  {0}: {1}'.format(target, unit.get_multiple_option(target)))

    print('Sync status:')
    for key, val in unit.get_sync_status().items():
        if isinstance(val, dict):
            print('  {0}:'.format(key))
            for name, state in val.items():
                print('    {0}: {1}'.format(name, state))
        else:
            print('  {0}: {1}'.format(key, val))

    return True


def handle_multiple_option(unit, args):
    ops = ('set', 'get')
    targets = unit.get_multiple_option_labels()
    if len(args) >= 2 and args[0] in targets and args[1] in ops:
        target = args[0]
        op = args[1]
        vals = unit.get_multiple_option_value_labels(target)
        if op == 'set' and len(args) >= 3 and args[2] in vals:
            val = args[2]
            unit.set_multiple_option(target, val)
            return True
        elif op == 'get':
            print(unit.get_multiple_option(target))
            return True

    print('Arguments for multiple-option command:')
    print('  multiple-option TARGET OP [ITEM]')
    print('    TARGET: [{0}]'.format('|'.join(targets)))
    print('    OP      [{0}]'.format('|'.join(ops)))
    for target in targets:
        vals = unit.get_multiple_option_value_labels(target)
        print('    ITEM    [{0}] if TARGET={1} and OP=set'.format(
            '|'.join(vals), target))
    return False


def handle_single_option(unit, args):
    ops = ('set', 'get')
    targets = unit.get_single_option_labels()
    if len(args) >= 1 and args[0] in targets:
        target = args[0]
        items = unit.get_single_option_item_labels(target)
        if len(args) >= 3 and args[1] in items and args[2] in ops:
            item = args[1]
            op = args[2]
            if op == 'set' and len(args) >= 4:
                enable = True if args[3] == '1' else False
                unit.set_single_option(target, item, enable)
                return True
            elif op == 'get':
                print(unit.get_single_option(target, item))
                return True
    print('Arguments for single-option command:')
    print('  single-option TARGET ITEM OP [ENABLE]')
    print('    TARGET: [{0}]'.format('|'.join(targets)))
    for target in targets:
        items = unit.get_single_option_item_labels(target)
        print('    ITEM    [{0}] if TARGET={1}'.format(
            '|'.join(items), target))
    print('    OP      [{0}]'.format('|'.join(ops)))
    print('    ENABLE: [0|1]')
    return False


def handle_mixer_src(unit, args):
    ops = ('set', 'get')
    targets = unit.get_mixer_labels()
    srcs = unit.get_mixer_src_labels()
    mute = unit.get_mixer_mute_db()
    minimum = unit.get_mixer_min_db()
    maximum = unit.get_mixer_max_db()
    if (len(args) >= 3 and args[0] in targets and args[1] in srcs
            and args[2] in ops):
        target = args[0]
        src = args[1]
        op = args[2]
        if op == 'set' and len(args) >= 4:
            db = float(args[3])
            unit.set_mixer_src(target, src, db)
            return True
        elif op == 'get':
            print(unit.get_mixer_src(target, src))
            return True
    print('Arguments for mixer-src command:')
    print('  mixer-src TARGET SRC OP [dB]')
    print('    TARGET: [{0}]'.format('|'.join(targets)))
    print('    SRC:    [{0}]'.format('|'.join(srcs)))
    print('    OP:     [{0}]'.format('|'.join(ops)))
    print('    dB:     [{0}, {1:.1f}..{2:.1f}] if OP=set'.format(
        mute, minimum, maximum))
    return False


def handle_output(unit, args):
    ops = ('set', 'get')
    targets = unit.get_out_labels()
    mute = unit.get_mixer_mute_db()
    minimum = unit.get_mixer_min_db()
    maximum = unit.get_mixer_max_db()
    if len(args) >= 2 and args[0] in targets and args[1] in ops:
        target = args[0]
        op = args[1]
        if op == 'set' and len(args) >= 3:
            db = float(args[2])
            unit.set_out_volume(target, db)
            return True
        elif op == 'get':
            print(unit.get_out_volume(target))
            return True
    print('Arguments for output command:')
    print('  output TARGET [dB]')
    print('    TARGET: [{0}]'.format('|'.join(targets)))
    print('    OP:     [{0}]'.format('|'.join(ops)))
    print('    dB:     [{0}, {1:.1f}..{2:.1f}] if OP=set'.format(
        mute, minimum, maximum))
    return False


cmds = {
    'status':           handle_status,
    'multiple-option':  handle_multiple_option,
    'single-option':    handle_single_option,
    'mixer-src':        handle_mixer_src,
    'output':           handle_output,
}

fullpath = CliKit.seek_snd_unit_path()
if fullpath:
    with FFUnit(fullpath) as unit:
        CliKit.dispatch_command(unit, cmds)
