// Copyright (c) 2013-2020, SIB - Swiss Institute of Bioinformatics and
//                          Biozentrum - University of Basel
// 
// 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.


#ifndef PROMOD3_GRAPH_HH
#define PROMOD3_GRAPH_HH

#include <vector>
#include <iostream>

namespace promod3 { namespace core {

class Graph{

public:

  Graph(int n);

  Graph(const Graph& other);

  ~Graph();

  Graph& operator = (const Graph& other);

  inline void Connect(int i, int j){
    adjacency_matrix_[i * n_ + j] = 1;
    adjacency_matrix_[j * n_ + i] = 1;
  }

  inline void Disconnect(int i, int j){
    adjacency_matrix_[i * n_ + j] = 0;
    adjacency_matrix_[j * n_ + i] = 0;
  }

  inline int IsConnected(int i, int j) const{
    return adjacency_matrix_[i * n_ + j];
  }

  int NumNodes() const { return n_; }

  Graph SubGraph(const std::vector<int>& indices) const;

  void ClearNode(int idx);

  void BuildClique(const std::vector<int>& indices);

  void ConnectedComponents(std::vector<std::vector<int> >& components) const;

  void GetNeighbours(int idx, std::vector<int>& neighbours) const;

  void NumConnections(std::vector<int>& connections) const;

  bool IsConnected() const;

private:
  int n_;
  int* adjacency_matrix_;
};

inline std::ostream& operator<<(std::ostream& o, const Graph& g) {
  for(int i = 0; i < g.NumNodes(); ++i){
    for(int j = 0; j < g.NumNodes(); ++j){
      o << g.IsConnected(i,j) << ' ';
    }
    o << '\n';
  }
  return o;
}

}} //ns

#endif
