/*
 * Copyright (c) 2018-2020 Arm Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include "CommonOptions.h"

#include "../Framework.h"
#include "../printers/Printers.h"
#include <unistd.h>

using namespace arm_compute::utils;

namespace arm_compute
{
namespace test
{
namespace framework
{
CommonOptions::CommonOptions(CommandLineParser &parser)
    : help(parser.add_option<ToggleOption>("help")),
      instruments(),
      iterations(parser.add_option<SimpleOption<int>>("iterations", 1)),
      log_format(),
      log_file(parser.add_option<SimpleOption<std::string>>("log-file")),
      log_level(),
      throw_errors(parser.add_option<ToggleOption>("throw-errors")),
      color_output(parser.add_option<ToggleOption>("color-output", isatty(STDOUT_FILENO))), // Only enable colors by default if we're running in a terminal
      pretty_console(parser.add_option<ToggleOption>("pretty-console", false)),
      json_file(parser.add_option<SimpleOption<std::string>>("json-file")),
      pretty_file(parser.add_option<SimpleOption<std::string>>("pretty-file")),
      log_streams()
{
    Framework                       &framework = Framework::get();
    std::set<InstrumentsDescription> allowed_instruments
    {
        std::pair<InstrumentType, ScaleFactor>(InstrumentType::ALL, ScaleFactor::NONE),
        std::pair<InstrumentType, ScaleFactor>(InstrumentType::NONE, ScaleFactor::NONE),
    };

    for(const auto &type : framework.available_instruments())
    {
        allowed_instruments.insert(type);
    }

    std::set<LogFormat> supported_log_formats
    {
        LogFormat::NONE,
        LogFormat::PRETTY,
        LogFormat::JSON,
    };

    std::set<LogLevel> supported_log_levels
    {
        LogLevel::NONE,
        LogLevel::CONFIG,
        LogLevel::TESTS,
        LogLevel::ERRORS,
        LogLevel::DEBUG,
        LogLevel::MEASUREMENTS,
        LogLevel::ALL,
    };

    instruments = parser.add_option<EnumListOption<InstrumentsDescription>>("instruments", allowed_instruments, std::initializer_list<InstrumentsDescription> { std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMER, ScaleFactor::NONE) });
    log_format  = parser.add_option<EnumOption<LogFormat>>("log-format", supported_log_formats, LogFormat::PRETTY);
    log_level   = parser.add_option<EnumOption<LogLevel>>("log-level", supported_log_levels, LogLevel::ALL);

    help->set_help("Show this help message");
    instruments->set_help("Set the profiling instruments to use");
    iterations->set_help("Number of iterations per test case");
    log_format->set_help("Output format for measurements and failures (affects only log-file)");
    log_file->set_help("Write output to file instead of to the console (affected by log-format)");
    log_level->set_help("Verbosity of the output");
    throw_errors->set_help("Don't catch fatal errors (useful for debugging)");
    color_output->set_help("Produce colored output on the console");
    pretty_console->set_help("Produce pretty output on the console");
    json_file->set_help("Write output to a json file.");
    pretty_file->set_help("Write output to a text file");
}
std::vector<std::unique_ptr<Printer>> CommonOptions::create_printers()
{
    std::vector<std::unique_ptr<Printer>> printers;

    if(pretty_console->value() && (log_file->is_set() || log_format->value() != LogFormat::PRETTY))
    {
        auto pretty_printer = std::make_unique<PrettyPrinter>();
        pretty_printer->set_color_output(color_output->value());
        printers.push_back(std::move(pretty_printer));
    }

    std::unique_ptr<Printer> printer;
    switch(log_format->value())
    {
        case LogFormat::JSON:
            printer = std::make_unique<JSONPrinter>();
            break;
        case LogFormat::NONE:
            break;
        case LogFormat::PRETTY:
        default:
            auto pretty_printer = std::make_unique<PrettyPrinter>();
            // Don't use colours if we print to a file:
            pretty_printer->set_color_output((!log_file->is_set()) && color_output->value());
            printer = std::move(pretty_printer);
            break;
    }

    if(log_file->is_set())
    {
        log_streams.push_back(std::make_shared<std::ofstream>(log_file->value()));
        if(printer != nullptr)
        {
            printer->set_stream(*log_streams.back().get());
        }
    }

    if(printer != nullptr)
    {
        printers.push_back(std::move(printer));
    }

    if(json_file->is_set())
    {
        printers.push_back(std::make_unique<JSONPrinter>());
        log_streams.push_back(std::make_shared<std::ofstream>(json_file->value()));
        printers.back()->set_stream(*log_streams.back().get());
    }

    if(pretty_file->is_set())
    {
        printers.push_back(std::make_unique<PrettyPrinter>());
        log_streams.push_back(std::make_shared<std::ofstream>(pretty_file->value()));
        printers.back()->set_stream(*log_streams.back().get());
    }

    return printers;
}
} // namespace framework
} // namespace test
} // namespace arm_compute
