/*
 * DisplayFactory.cpp
 *
 *  Created on: December 28, 2019
 *      Author: Andreas Schneider, Johannes Wendel, Jonas Zeunert
 */

#include "output/DisplayBoardPinController.h"
#include "output/items/detail/EightDigitDisplay.h"
#include "output/items/detail/SevenDigitDisplay.h"
#include "DisplayFactory.h"

namespace flippR_driver
{
namespace output
{

DisplayFactory::DisplayFactory(nlohmann::json &object, std::shared_ptr<DisplayBoardPinController> pin_controller) :
  ItemFactory{object, pin_controller}
{
  this->create_pin_map();
  pin_controller->set_pin_map(this->pin_map);
}

std::map<std::string, std::shared_ptr<items::Display>> DisplayFactory::getItemMap()
{
  std::map<std::string, std::shared_ptr<items::Display>> display_map;
  auto displays = this->object.at(config_path::display_list);
  for (auto & display : displays)
  {
    auto name = display.at(config_path::item_name).get<std::string>();
    auto address = display.at(config_path::item_address).get<uint8_t>();
    auto digits = display.at(config_path::display_digits).get<uint8_t>();
    if (digits == 8)
      display_map.emplace(name, std::dynamic_pointer_cast<items::Display>(std::make_shared<items::detail::EightDigitDisplay>(address, name)));
    else if (digits == 7)
      display_map.emplace(name, std::dynamic_pointer_cast<items::Display>(std::make_shared<items::detail::SevenDigitDisplay>(address, name)));
    else
      throw new std::logic_error{"Display digits can either be 7 or 8"};
  }
  return display_map;
}

void DisplayFactory::create_pin_map()
{
  nlohmann::json board_config = this->object.at(config_path::display_board);
  this->pin_map["run"] = board_config.at(config_path::run_pin);
  this->pin_map["lt"] = board_config.at(config_path::display_lt_pin);

  nlohmann::json segment_select = board_config.at(config_path::display_segement_select);
  this->pin_map["segment_select_A"] = segment_select.at("A");
  this->pin_map["segment_select_B"] = segment_select.at("B");
  this->pin_map["segment_select_C"] = segment_select.at("C");

  nlohmann::json digit_select = board_config.at(config_path::display_digit_select);
  this->pin_map["digit_select_A"] = digit_select.at("A");
  this->pin_map["digit_select_B"] = digit_select.at("B");
  this->pin_map["digit_select_C"] = digit_select.at("C");
  this->pin_map["digit_select_D"] = digit_select.at("D");
}

}
}
