#  Copyright (c) 1997-2015
#  Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
#  http://www.polymake.org
#
#  This program 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 2, or (at your option) any
#  later version: http://www.gnu.org/licenses/gpl.txt.
#
#  This program 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.
#-------------------------------------------------------------------------------

# @category Symmetry
# A cone which is generated by a group and a generating set of inequalities (+equations) 
# or input rays (+input_lineality).
# The cone is the intersection or the convex hull of all inequalities or input rays in 
# the orbit of the generating set under the [[GENERATING_GROUP]]. 
# @tparam Scalar default: [[Rational]]
declare object SymmetricCone<Scalar=Rational> : Cone<Scalar> {

########################################################
# properties
########################################################


# The group which generates the cone by being applied to some 
# [[GEN_INPUT_RAYS]] (and [[GEN_INPUT_LINEALITY]]) or some
# [[GEN_INEQUALITIES]] (and [[GEN_EQUATIONS]]).
property GENERATING_GROUP : group::GroupOfCone;

rule initial : GENERATING_GROUP {
   if ($this->GENERATING_GROUP->DOMAIN != $domain_OnCoords) {
      croak( "Only actions on coordinates are allowed! (i.e. DOMAIN must be equal to \$domain_OnCoords)" );
   }
}

#*******************************************************
#* generating input properties and representatives
#*******************************************************

# Some generating input rays for the symmetric cone; redundancies are allowed.
#
# Input section only.  Ask for [[group::GroupOfCone::REPRESENTATIVE_RAYS|REPRESENTATIVE_RAYS]] if you want a list of representatives for the 
# orbits of rays of a symmetric cone.
property GEN_INPUT_RAYS : Matrix<Scalar> {

  method canonical { 
      my ($this,$M)=@_;
      canonicalize_rays($M); 
      if ($this->isa("Polytope")) {
          canonicalize_polytope_generators($M);
      }
  }
}


# The number of [[GEN_INPUT_RAYS]].
property N_GEN_INPUT_RAYS : Int;


#*******************************************************
#* input lineality properties
#*******************************************************

# Some generating input rays for (a subset of) the lineality space of the symmetric cone.
# Redundancies are allowed.
#
# Input section only.
property GEN_INPUT_LINEALITY : Matrix<Scalar> {
  sub canonical { &canonicalize_rays; }
}


# The number of [[GEN_INPUT_LINEALITY]].
property N_GEN_INPUT_LINEALITY : Int;


#*******************************************************
#* inequality/facet properties
#*******************************************************

# Some generating inequalities for the symmetric cone; redundancies are allowed.
#
# Input section only.  Ask for [[group::GroupOfCone::REPRESENTATIVE_FACETS|REPRESENTATIVE_FACETS]] if you want a list of representatives for the 
# orbits of facets of a symmetric cone.
property GEN_INEQUALITIES : Matrix<Scalar> {

   method canonical {
      my $self=shift;
      $self->canonical_ineq(@_);
   }
}


# The number of [[GEN_INEQUALITIES]].
property N_GEN_INEQUALITIES : Int;



#*******************************************************
#* generating equations
#*******************************************************


# Some generating equations for (a subset of) the linear span of the symmetric cone.
# Redundancies are allowed.
#
# Input section only.
property GEN_EQUATIONS : Matrix<Scalar>;


# The number of [[GEN_EQUATIONS]].
property N_GEN_EQUATIONS : Int;




########################################################
# rules
########################################################

rule N_GEN_INPUT_RAYS : GEN_INPUT_RAYS {
    $this->N_GEN_INPUT_RAYS=$this->GEN_INPUT_RAYS->rows;
}

rule N_GEN_INPUT_LINEALITY : GEN_INPUT_LINEALITY {
    $this->N_GEN_INPUT_LINEALITY=$this->GEN_INPUT_LINEALITY->rows;
}

rule N_GEN_INEQUALITIES : GEN_INEQUALITIES {
    $this->N_GEN_INEQUALITIES=$this->GEN_INEQUALITIES->rows;
}

rule N_GEN_EQUATIONS : GEN_EQUATIONS {
    $this->N_GEN_EQUATIONS=$this->GEN_EQUATIONS->rows;
}

#*******************************************************

rule GENERATING_GROUP.N_ORBITS_OF_INPUT_RAYS : GENERATING_GROUP.INPUT_RAYS_IN_ORBITS {
    $this->GENERATING_GROUP->N_ORBITS_OF_INPUT_RAYS=$this->GENERATING_GROUP->INPUT_RAYS_IN_ORBITS->size;
}


rule GENERATING_GROUP.N_ORBITS_OF_INEQUALITIES : GENERATING_GROUP.INEQUALITIES_IN_ORBITS {
    $this->GENERATING_GROUP->N_ORBITS_OF_INEQUALITIES=$this->GENERATING_GROUP->INEQUALITIES_IN_ORBITS->size;
}



##################################################################################################
#FIXME: evtl. RAY_LABELS für graphische Darstellung VISUAL_ORBIT_GRAPH?



# Generates an array with a specified number of different colors.
# @param int number      the number of colors
# @return array          the colors as strings 
sub generateColors{
    my $number=$_[0];
# not really implemented yet!
    my @FIFTEEN_COLORS=("chocolate1","salmon1","plum1","LightGreen","azure","LightSlateGrey","MidnightBlue","DarkOliveGreen","IndianRed","LavenderBlush","orange","green","red","blue","yellow");
    my @colors=();
    for(my $i=0;$i<$number;$i++){
        if($i<15){
            $colors[$i]=$FIFTEEN_COLORS[14-$i];
        } else {
            $colors[$i]="black";
        }
    }
    return @colors;
}


# FIXME: VISUAL_ORBIT_COLORED_GRAPH should be a method of a SymmetricGraph object (to be defined!)!

# Visualizes the graph of a symmetric cone: 
# All nodes belonging to one orbit get the same color.
# @return Visual::PolytopeGraph
user_method VISUAL_ORBIT_COLORED_GRAPH(%Visual::Graph::decorations, { seed => undef }){
    my ($this, $decor, $seed)=@_;
#    my $symPoly=new Polytope<Rational>($this); #FIXME: just because cones cannot be visualized yet
#    my $VG=$symPoly->VISUAL_GRAPH($decor, $seed);
    my $VG=$this->VISUAL_GRAPH($decor, $seed);
    my @colors=generateColors($this->GENERATING_GROUP->N_ORBITS_OF_RAYS);
    my @nodeColors;
    for(my $i=0;$i<$this->GENERATING_GROUP->N_ORBITS_OF_RAYS;$i++){
        foreach my $ray_index(@{$this->GENERATING_GROUP->RAYS_IN_ORBITS->[$i]}){
            $nodeColors[$ray_index]=$colors[$i]; #each ray gets the color(=number) of its orbit
        }
    }
    $VG->basis_graph->NodeColor=\@nodeColors;
    visualize($VG);
}

}

# Local Variables:
# mode: perl
# cperl-indent-level: 3
# indent-tabs-mode:nil
# End:
