#ifndef BUYSELL_H
#define BUYSELL_H

#include <iostream>

typedef uint8_t port_type;

enum PRODUCT { FUEL = 0, ORG = 1, EQU = 2 };

// Class 0 : Special
// Class 9 : StarDock BBB

// typedef std::array<bool, 3> buysell;
struct buysell {
  bool foe[3];
  bool operator==(const buysell& rhs) const;
  friend std::ostream& operator<<(std::ostream& os, const buysell& bs);
};

// ostream& operator<<(std::ostream& os, const buysell& bs);

// typedef std::array<char, 3> buysell_text;
struct buysell_text {
  char txt[3];
  bool operator==(const buysell_text& rhs) const;
  friend std::ostream& operator<<(std::ostream& os, const buysell_text& bst);
};

/*
1 : "BBS", TTF
2 : "BSB", TFT
3 : "SBB", FTT
4 : "SSB", FFT
5 : "SBS", FTF
6 : "BSS", TFF
7 : "SSS", FFF
8 : "BBB", TTT
9 : "BBB", TTT
*/

/* convert type to buysell flag values, buy = true */

constexpr buysell get_buysell(port_type type) {
  switch (type) {
    case 1:  // BBS TTF
      return {true, true, false};
    case 2:  // BSB TFT
      return {true, false, true};
    case 3:  // SBB FTT
      return {false, true, true};
    case 4:  // SSB FFT
      return {false, false, true};
    case 5:  // SBS FTF
      return {false, true, false};
    case 6:  // BSS TFF
      return {true, false, false};
    case 7:  // SSS FFF
      return {false, false, false};
    case 8:  // BBB TTT
    case 9:
      return {true, true, true};
    default:
      throw std::invalid_argument("invalid buysell type");
  }
}

constexpr buysell_text text_from_buysell(const buysell market) {
  buysell_text text{'?', '?', '?'};
  for (int x = 0; x < 3; ++x) {
    text.txt[x] = market.foe[x] ? 'B' : 'S';
  }
  return text;
}

constexpr buysell_text text_from_type(port_type type) {
  switch (type) {
    case 1:
      return buysell_text{'B', 'B', 'S'};
    case 2:
      return buysell_text{'B', 'S', 'B'};
    case 3:
      return buysell_text{'S', 'B', 'B'};
    case 4:
      return buysell_text{'S', 'S', 'B'};
    case 5:
      return buysell_text{'S', 'B', 'S'};
    case 6:
      return buysell_text{'B', 'S', 'S'};
    case 7:
      return buysell_text{'S', 'S', 'S'};
    case 8:
    case 9:
      return buysell_text{'B', 'B', 'B'};
    default:
      throw std::invalid_argument("invalid text_from_type type");
  }
}

constexpr uint8_t type_from_buysell(const buysell market) {
  if (market.foe[0]) {
    if (market.foe[1]) {
      if (market.foe[2]) {
        return 8;  // BBB TTT
      } else
        return 1;  // BBS TTF
    } else {
      if (market.foe[2]) {
        return 2;  // BSB TFT
      } else
        return 6;  // BSS TFF
    }
  } else {
    if (market.foe[1]) {
      if (market.foe[2]) {
        return 3;  // SBB FTT
      } else
        return 5;  // SBS FTF
    } else {
      if (market.foe[2]) {
        return 4;  // SSB FFT
      } else
        return 7;  // SSS FFF
    }
  }
}

constexpr buysell invert_buysell(const buysell market) {
  if (market.foe[0]) {
    if (market.foe[1]) {
      if (market.foe[2]) {
        return {false, false, false};  // BBB TTT
      } else
        return {false, false, true};  // BBS TTF
    } else {
      if (market.foe[2]) {
        return {false, true, false};  // BSB TFT
      } else
        return {false, true, true};  // BSS TFF
    }
  } else {
    if (market.foe[1]) {
      if (market.foe[2]) {
        return {true, false, false};  // SBB FTT
      } else
        return {true, false, true};  // SBS FTF
    } else {
      if (market.foe[2]) {
        return {true, true, false};  // SSB FFT
      } else
        return {true, true, true};  // SSS FFF
    }
  }
}

#endif