#pragma once

class LUTCircuit;

#include "gate.h"

class LUT {
public:
  LUT(Gate *gate, LUTCircuit *circuit);

  LUTCircuit *C;

  Gate *gate;

  bool isPI, isPO;

  std::vector<LUT *> fanins;

  std::vector<LUT *> fanouts;

  std::vector<LUT *> reigon;
  std::vector<LUT *> update_reigon;

  std::vector<LUT *> add_update_to_this;

  std::vector<Gate *> inner_gates;

  std::vector<Gate *> __gate_fanins;

  std::unordered_map<Gate *, int> input_id;

  int &value;
  const char *name;

  int *value_table;

  struct FaultInfo {
    int fd[2];
    int fpl[2];
  } **fault_table;

  std::vector<FaultInfo *> fault_info;

  std::unordered_set<LUT *> update_luts;

  void init_lookup_table();

  // local search

  bool vsat, vunat_cost;
  bool uptag, up_cost;
  int fd[2];
  int fpl[2];
  int is_good_var;
  int tabu;

  int cal_value();
  void cal_fault_info(int *t_fd, int *t_fpl);
  void get_fault_info(Gate *gate, int *t_fd, int *t_fpl);

  // score
  int score;
  int score_value_unsatisfied_cost;
  int score_fault_detected_weight;
  int score_fault_propagated_weight;
  int score_fault_update_cost;

  void cal_score();
  void cal_update();
};