/**
 * Copyright (C) 2017 IBM Corporation
 *
 * 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 "registration.hpp"
#include "targeting.hpp"

#include <stdlib.h>

#include <experimental/filesystem>
#include <fstream>

#include <gtest/gtest.h>

using namespace openpower::util;
using namespace openpower::targeting;
namespace fs = std::experimental::filesystem;

ProcedureMap Registration::procedures;

constexpr auto masterDir = "/tmp";

class TargetingTest : public ::testing::Test
{
  protected:
    virtual void SetUp()
    {
        char dir[50];
        strcpy(dir, masterDir);
        strcat(dir, "/targetingXXXXXX");

        auto path = mkdtemp(dir);
        assert(path != nullptr);

        _slaveBaseDir = path;

        _slaveDir = _slaveBaseDir / "fsi1";
        fs::create_directory(_slaveDir);
    }

    virtual void TearDown()
    {
        fs::remove_all(_slaveDir);
        fs::remove_all(_slaveBaseDir);
    }

    fs::path _slaveBaseDir;
    fs::path _slaveDir;
};

TEST_F(TargetingTest, CreateTargets)
{

    // Test that we always create the first Target
    {
        Targeting targets{masterDir, _slaveDir};
        ASSERT_EQ(targets.size(), 1);

        auto t = targets.begin();
        ASSERT_EQ((*t)->getPos(), 0);

        ASSERT_EQ((*t)->getCFAMPath(), masterDir);
    }

    // Test that we can create multiple Targets
    {
        // make some fake slave entries
        std::ofstream(_slaveDir / "slave@01:00");
        std::ofstream(_slaveDir / "slave@02:00");
        std::ofstream(_slaveDir / "slave@03:00");
        std::ofstream(_slaveDir / "slave@04:00");

        Targeting targets{masterDir, _slaveDir};

        ASSERT_EQ(targets.size(), 5);

        int i = 0;

        for (const auto& t : targets)
        {
            fs::path path;

            ASSERT_EQ(t->getPos(), i);

            if (0 == i)
            {
                path = masterDir;
            }
            else
            {
                std::ostringstream subdir;
                subdir << "slave@0" << i << ":00/raw";

                path = _slaveDir;
                path /= subdir.str();
            }

            ASSERT_EQ(t->getCFAMPath(), path);
            i++;
        }
    }
}

void func1()
{
    std::cout << "Hello\n";
}

void func2()
{
    std::cout << "World\n";
}

REGISTER_PROCEDURE("hello", func1);
REGISTER_PROCEDURE("world", func2);

TEST(RegistrationTest, TestReg)
{
    int count = 0;
    for (const auto& p : Registration::getProcedures())
    {
        std::cout << p.first << std::endl;
        p.second();
        count++;
    }

    ASSERT_EQ(count, 2);
}