// -*- coding: utf-8 -*-
// Copyright (C) 2014  Laboratoire de Recherche et Developpement
// de l'Epita (LRDE).
// Copyright (C) 2004, 2011  Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
// et Marie Curie.
//
// This file is part of Spot, a model checking library.
//
// Spot is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// Spot is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
// License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include <sstream>
#include "rundotdec.hh"

namespace spot
{

  tgba_run_dotty_decorator::tgba_run_dotty_decorator(const
						     const_tgba_run_ptr& run)
    : run_(run)
  {
    int n = 1;
    for (tgba_run::steps::const_iterator i = run->prefix.begin();
	 i != run->prefix.end(); ++i, ++n)
      map_[i->s].first.emplace_back(i, n);
    for (tgba_run::steps::const_iterator i = run->cycle.begin();
	 i != run->cycle.end(); ++i, ++n)
      map_[i->s].second.emplace_back(i, n);
  }

  tgba_run_dotty_decorator::~tgba_run_dotty_decorator()
  {
  }

  std::string
  tgba_run_dotty_decorator::state_decl(const const_tgba_ptr&,
				       const state* s, int,
				       tgba_succ_iterator*,
				       const std::string& label,
				       bool accepting)
  {
    step_map::const_iterator i = map_.find(s);
    std::string acc = accepting ? ", peripheries=2" : "";
    if (i == map_.end())
      return "[label=\"" + label + acc + "\"]";

    std::ostringstream os;
    std::string sep = "(";
    bool in_prefix = false;
    bool in_cycle = false;
    for (auto j: i->second.first)
      {
	os << sep << j.second;
	sep = ", ";
	in_prefix = true;
      }
    if (sep == ", ")
      sep = "; ";
    for (auto j: i->second.second)
      {
	os << sep << j.second;
	sep = ", ";
	in_cycle = true;
      }
    assert(in_cycle || in_prefix);
    os << ")\\n" << label;
    std::string color = in_prefix ? (in_cycle ? "violet" : "blue") : "red";
    return "[label=\"" + os.str() + "\", style=bold, color="
      + color + acc + "]";
  }

  std::string
  tgba_run_dotty_decorator::link_decl(const const_tgba_ptr&,
				      const state* in_s, int,
				      const state* out_s, int,
				      const tgba_succ_iterator* si,
				      const std::string& label)
  {
    step_map::const_iterator i = map_.find(in_s);
    if (i != map_.end())
      {
	std::ostringstream os;
	std::string sep = "(";
	bool in_prefix = false;
	bool in_cycle = false;
	for (step_set::const_iterator j = i->second.first.begin();
	     j != i->second.first.end(); ++j)
	  if (j->first->label == si->current_condition()
	      && j->first->acc == si->current_acceptance_conditions())
	    {
	      tgba_run::steps::const_iterator j2 = j->first;
	      ++j2;
	      if (j2 == run_->prefix.end())
		j2 = run_->cycle.begin();
	      if (out_s->compare(j2->s))
		continue;

	      os << sep << j->second;
	      sep = ", ";
	      in_prefix = true;
	    }
	if (sep == ", ")
	  sep = "; ";
	for (step_set::const_iterator j = i->second.second.begin();
	     j != i->second.second.end(); ++j)
	  if (j->first->label == si->current_condition()
	      && j->first->acc == si->current_acceptance_conditions())
	    {
	      tgba_run::steps::const_iterator j2 = j->first;
	      ++j2;
	      if (j2 == run_->cycle.end())
		j2 = run_->cycle.begin();
	      if (out_s->compare(j2->s))
		continue;

	      os << sep << j->second;
	      sep = ", ";
	      in_cycle = true;
	    }
	os << ")\\n";
	if (in_prefix || in_cycle)
	  {
	    std::string
	      color = in_prefix ? (in_cycle ? "violet" : "blue") : "red";
	    return ("[label=\"" + os.str() + label
		    + "\", style=bold, color=" + color + "]");

	  }
      }
    return "[label=\"" + label + "\"]";
  }



}
