/*
 * 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"
#if !defined(_WIN64)
#include <unistd.h>
#endif // !defined(_WIN64)

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")),
#if !defined(_WIN64)
     color_output(parser.add_option<ToggleOption>("color-output", isatty(STDOUT_FILENO))), // Only enable colors by default if we're running in a terminal
#endif // !defined(_WIN64)
      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
