/* -*- C++ -*-
 *
 * This file is a part of LEMON, a generic C++ optimization library
 *
 * Copyright (C) 2003-2006
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
 *
 * Permission to use, modify and distribute this software is granted
 * provided that this copyright notice appears in all copies. For
 * precise terms see the accompanying LICENSE file.
 *
 * This software is provided "AS IS" with no warranty of any kind,
 * express or implied, and with no claim as to its suitability for any
 * purpose.
 *
 */

#include <lemon/concept/bpugraph.h>
#include <lemon/list_graph.h>
#include <lemon/smart_graph.h>
#include <lemon/full_graph.h>
#include <lemon/grid_ugraph.h>

#include <lemon/graph_utils.h>

#include "test_tools.h"


using namespace lemon;
using namespace lemon::concept;

void check_concepts() {

  { // checking graph components
    checkConcept<BaseBpUGraphComponent, BaseBpUGraphComponent >();

    checkConcept<IDableBpUGraphComponent<>, 
      IDableBpUGraphComponent<> >();

    checkConcept<IterableBpUGraphComponent<>, 
      IterableBpUGraphComponent<> >();

    checkConcept<MappableBpUGraphComponent<>, 
      MappableBpUGraphComponent<> >();

  }
  {
    checkConcept<BpUGraph, ListBpUGraph>();
    
    checkConcept<BpUGraph, SmartBpUGraph>();
    
    checkConcept<BpUGraph, FullBpUGraph>();
    
    checkConcept<BpUGraph, BpUGraph>();
    
  }
}

template <typename Graph>
void check_item_counts(Graph &g, int an, int bn, int e) {
  int nn = 0;
  for (typename Graph::NodeIt it(g); it != INVALID; ++it) {
    ++nn;
  }

  check(nn == an + bn, "Wrong node number.");
  check(countNodes(g) == an + bn, "Wrong node number.");

  int ann = 0;
  for (typename Graph::ANodeIt it(g); it != INVALID; ++it) {
    ++ann;
  }

  check(ann == an, "Wrong node number.");
  check(countANodes(g) == an, "Wrong node number.");

  int bnn = 0;
  for (typename Graph::BNodeIt it(g); it != INVALID; ++it) {
    ++bnn;
  }

  check(bnn == bn, "Wrong node number.");
  check(countBNodes(g) == bn, "Wrong node number.");

  int ee = 0;
  for (typename Graph::EdgeIt it(g); it != INVALID; ++it) {
    ++ee;
  }

  check(ee == 2*e, "Wrong edge number.");
  check(countEdges(g) == 2*e, "Wrong edge number.");

  int uee = 0;
  for (typename Graph::UEdgeIt it(g); it != INVALID; ++it) {
    ++uee;
  }

  check(uee == e, "Wrong uedge number.");
  check(countUEdges(g) == e, "Wrong uedge number.");
}

template <typename Graph>
void check_graph() {

  typedef typename Graph::Node Node;
  typedef typename Graph::UEdge UEdge;
  typedef typename Graph::Edge Edge;
  typedef typename Graph::NodeIt NodeIt;
  typedef typename Graph::UEdgeIt UEdgeIt;
  typedef typename Graph::EdgeIt EdgeIt;

  Graph g;

  check_item_counts(g, 0, 0, 0);

  Node
    an1 = g.addANode(),
    an2 = g.addANode(),
    an3 = g.addANode(),
    bn1 = g.addBNode(),
    bn2 = g.addBNode();

  UEdge
    e1 = g.addEdge(an1, bn1),
    e2 = g.addEdge(an2, bn1),
    e3 = g.addEdge(an3, bn2);

  check_item_counts(g, 3, 2, 3);
}

int main() {
  check_concepts();

  check_graph<ListBpUGraph>();
  check_graph<SmartBpUGraph>();

  {
    FullBpUGraph g(5, 10);
    check_item_counts(g, 5, 10, 50);
  }

  std::cout << __FILE__ ": All tests passed.\n";

  return 0;
}
