#############################################################################
##
##  ToricDivisors.gi         ToricVarieties package
##
##  Copyright 2011-2016, Sebastian Gutsche, TU Kaiserslautern
##                       Martin Bies,       ITP Heidelberg
##
##  The category of toric divisors of a toric variety
##
#############################################################################

#################################
##
## Representations
##
#################################

DeclareRepresentation( "IsToricDivisorRep",
                       IsToricDivisor and IsAttributeStoringRep,
                       [ AmbientToricVariety, UnderlyingGroupElement ]
                      );

BindGlobal( "TheFamilyOfToricDivisors",
        NewFamily( "TheFamilyOfToricDivisors" , IsToricDivisor ) );

BindGlobal( "TheTypeToricDivisor",
        NewType( TheFamilyOfToricDivisors,
                 IsToricDivisorRep ) );

#################################
##
## Properties
##
#################################

##
InstallMethod( IsPrincipal,
               "for toric divisors",
               [ IsToricDivisor ],
               
  function( divisor )
    
    return IsZero( ClassOfDivisor( divisor ) );
    
end );

##
InstallMethod( IsPrimedivisor,
               "for toric divisors",
               [ IsToricDivisor ],
               
  function( divisor )
    
    divisor := UnderlyingGroupElement( divisor );
    
    divisor := UnderlyingListOfRingElements( divisor );
    
    if ForAll( divisor, i -> i = 1 or i = 0 ) and Sum( divisor ) = 1 then
        
        return true;
        
    fi;
    
    return false;
    
end );

##
InstallMethod( IsCartier,
               "for toric divisors",
               [ IsToricDivisor ],
               
  function( divisor )
    local raysincones, rays, n, i, m, j, M, groupel, rayel, cartdata;
    
    rays := RayGenerators( FanOfVariety( AmbientToricVariety( divisor ) ) );
    
    raysincones := RaysInMaximalCones( FanOfVariety( AmbientToricVariety( divisor ) ) );
    
    n := Length( raysincones );
    
    m := Length( rays );
    
    cartdata := [ 1 .. n ];
    
    groupel := UnderlyingListOfRingElements( UnderlyingGroupElement( divisor ) );
    
    for i in [ 1 .. n ] do
        
        M := [ ];
        
        rayel := [ ];
        
        for j in [ 1 .. m ] do
            
            if raysincones[ i ][ j ] = 1 then
                
                Add( M, rays[ j ] );
                
                Add( rayel, - groupel[ j ] );
                
            fi;
            
        od;
        
        j := HomalgMatrix( rayel, Length( M ), 1, HOMALG_MATRICES.ZZ );
        
        M := HomalgMatrix( M, HOMALG_MATRICES.ZZ );
        
        j := LeftDivide( M, j );
        
        if j = fail then
            
            return false;
            
        fi;
        
        cartdata[ i ] := EntriesOfHomalgMatrix( j );
        
    od;
    
    SetCartierData( divisor, cartdata );
    
    return true;
    
end );

##
InstallMethod( IsAmple,
               " for toric divisors",
               [ IsToricDivisor ],
               
  function( divisor )
    local rays, raysincones, cartdata, groupel, l, i, multlist, j;
    
    rays := AmbientToricVariety( divisor );
    
    if not IsComplete( rays ) or not IsNormalVariety( rays ) then
        
        Error( "computation may be wrong up to unfulfilled preconditions\n" );
        
    fi;
    
    if not IsBasepointFree( divisor ) then
        
        return false;
        
    fi;
    
    groupel := UnderlyingListOfRingElements( UnderlyingGroupElement( divisor ) );
    
    l := Length( groupel );
    
    Apply( groupel, i -> -i );
    
    rays := RayGenerators( FanOfVariety( AmbientToricVariety( divisor ) ) );
    
    cartdata := CartierData( divisor );
    
    raysincones := RaysInMaximalCones( FanOfVariety( AmbientToricVariety( divisor ) ) );
    
    for i in [ 1 .. Length( cartdata ) ] do
        
        for j in [ 1 .. l ] do
            
            if raysincones[ i ][ j ] = 0 then
                
                multlist := Sum( List( [ 1 .. Length( cartdata[ i ] ) ], k -> rays[ j ][ k ] * cartdata[ i ][ k ] ) );
                
                if multlist <= groupel[ j ] then
                    
                    return false;
                    
                fi;
                
            fi;
            
        od;
        
    od;
    
    return true;
    
end );

##
InstallMethod( IsBasepointFree,
               "for toric divisors",
               [ IsToricDivisor ],
               
  function( divisor )
    local rays, cartdata, groupel, l, i, multlist, j;
    
    if HasTorusfactor( AmbientToricVariety( divisor ) ) then
        
        Error( "variety has torusfactors, computation may be wrong\n" );
        
    fi;
    
# #     if not IsComplete( AmbientToricVariety( divisor ) ) then
# #         
# #         Error( "variety is not complete, computation may be wrong." );
# #         
# #     fi;
    
    if not IsCartier( divisor ) then
        
        return false;
        
    fi;
    
    groupel := UnderlyingListOfRingElements( UnderlyingGroupElement( divisor ) );
    
    l := Length( groupel );
    
    Apply( groupel, i -> -i );
    
    rays := RayGenerators( FanOfVariety( AmbientToricVariety( divisor ) ) );
    
    cartdata := CartierData( divisor );
    
    for i in cartdata do
        
        multlist := List( rays, k -> Sum( [ 1 .. Length( k ) ], j -> k[j]*i[j] ) );
        
        if not ForAll( [ 1..l ], j -> multlist[ j ] >= groupel[ j ] ) then
            
            return false;
            
        fi;
        
    od;
    
    return true;
    
end );

##
InstallMethod( IsVeryAmple,
               "for toric divisors",
               [ IsToricDivisor and IsAmple ],
               
  function( divisor )
    
    return IsVeryAmple( PolytopeOfDivisor( divisor ) );
    
end );

##
## RedispatchOnCondition( IsVeryAmple, true, [ IsToricDivisor and IsAmple ], [ PolytopeOfDivisor ], 1 );

##
RedispatchOnCondition( IsVeryAmple, true, [ IsToricDivisor ], [ IsAmple ], 0 );


#################################
##
## Attributes
##
#################################

##
InstallMethod( ClassOfDivisor,
               "for toric divisors",
               [ IsToricDivisor ],
               
  function( divisor )

    return ApplyMorphismToElement( MapFromWeilDivisorsToClassGroup( AmbientToricVariety( divisor ) ),
                                   UnderlyingGroupElement( divisor )
                                  );

end );

##
InstallMethod( CartierData,
               "for toric divisors",
               [ IsToricDivisor and IsCartier ],
               
  function( divisor )
    local raysincones, rays, n, i, m, j, M, groupel, rayel, cartdata;
    
    rays := RayGenerators( FanOfVariety( AmbientToricVariety( divisor ) ) );
    
    raysincones := RaysInMaximalCones( FanOfVariety( AmbientToricVariety( divisor ) ) );
    
    n := Length( raysincones );
    
    m := Length( rays );
    
    cartdata := [ 1 .. n ];
    
    groupel := UnderlyingListOfRingElements( UnderlyingGroupElement( divisor ) );
    
    for i in [ 1 .. n ] do
        
        M := [ ];
        
        rayel := [ ];
        
        for j in [ 1 .. m ] do
            
            if raysincones[ i ][ j ] = 1 then
                
                Add( M, rays[ j ] );
                
                Add( rayel, - groupel[ j ] );
                
            fi;
            
        od;
        
        j := HomalgMatrix( rayel, Length( M ), 1, HOMALG_MATRICES.ZZ );
        
        M := HomalgMatrix( M, HOMALG_MATRICES.ZZ );
        
        j := LeftDivide( M, j );
        
        if j = fail then
            
            return false;
            
        fi;

        # this line causes problems
        #cartdata[ i ] := HomalgModuleElement( j, CharacterLattice( AmbientToricVariety( divisor ) ) );
        # resolution is this here, which makes use of yet another bug, namely EntriesOfHomalgMatrix does in my opinion not operate correctly
        cartdata[ i ] := EntriesOfHomalgMatrix( j );
    od;
    
    return cartdata;

end );

##
InstallMethod( PolytopeOfDivisor,
               "for toric divisors",
               [ IsToricDivisor ],
               
  function( divisor )
    local rays, divlist;
    
    rays := RayGenerators( FanOfVariety( AmbientToricVariety( divisor ) ) );
    
    divlist := UnderlyingListOfRingElements( UnderlyingGroupElement( divisor ) );
    
    divlist := List( [ 1 .. Length( rays ) ], i -> Concatenation( [ divlist[ i ] ], rays[ i ] ) );
    
    return PolytopeByInequalities( divlist );
    
end );

##
InstallMethod( BasisOfGlobalSections,
               "for toric divisors",
               [ IsToricDivisor ],
               
  function( divisor )
    local points, divisor_polytope;
    
    divisor_polytope := PolytopeOfDivisor( divisor );
    
    if not IsBounded( divisor_polytope ) then
        
        Error( "list is infinite, cannot compute characters\n" );
        
    fi;
    
    points := LatticePoints( divisor_polytope );
    
    return List( points, i -> CharacterToRationalFunction( i, AmbientToricVariety( divisor ) ) );
    
end );

##
InstallMethod( IntegerForWhichIsSureVeryAmple,
               "for toric divisors",
               [ IsToricDivisor and IsAmple ],
               
  function( divisor )
    local vari;
    
    vari := AmbientToricVariety( divisor );
    
    if IsSmooth( vari ) and IsComplete( vari ) then
        
        return 1;
        
    fi;
    
    if Dimension( vari ) >= 2 then
        
        return Dimension( vari ) - 1;
        
    fi;
    
    TryNextMethod();
    
end );

##
InstallMethod( UnderlyingToricVariety,
               "for prime divisors",
               [ IsToricDivisor and IsPrimedivisor ],
               
  function( divisor )
    local pos, vari, cones, i, neuvar, ray;
    
    pos := Position( UnderlyingListOfRingElements( UnderlyingGroupElement( divisor ) ), 1 );
    
    vari := AmbientToricVariety( divisor );
    
    vari := FanOfVariety( vari );
    
    cones := RaysInMaximalCones( vari );
    
    neuvar := [ ];
    
    for i in [ 1 .. Length( cones ) ] do
        
        if cones[ i ][ pos ] = 1 then
            
            neuvar := Concatenation( neuvar, [ i ] );
            
        fi;
        
    od;
    
    ray := Rays( vari )[ pos ];
    
    ray := ByASmallerPresentation( FactorGridMorphism( ray ) );
    
    cones := MaximalCones( vari ){ neuvar };
    
    cones := List( cones, HilbertBasis );
    
    cones := List( cones, i -> List( i, j -> HomalgMap( HomalgMatrix( [ j ], HOMALG_MATRICES.ZZ ), 1 * HOMALG_MATRICES.ZZ, ContainingGrid( vari ) ) ) );
    
    cones := List( cones, i -> List( i, j -> UnderlyingListOfRingElements( ApplyMorphismToElement( ray, HomalgElement( j ) ) ) ) );
    
    cones := Fan( cones );
    
    neuvar := ToricSubvariety( ToricVariety( cones ), AmbientToricVariety( divisor ) );
    
    SetIsClosedSubvariety( neuvar, true );
    
    SetIsOpen( neuvar, false );
    
    return neuvar;
    
end );

##
InstallMethod( DegreeOfDivisor,
               "for toric divisors",
               [ IsToricDivisor ],
               
  function( divisor )
    
    return Sum( UnderlyingListOfRingElements( UnderlyingGroupElement( divisor ) ) );
    
end );

##
InstallMethod( MonomsOfCoxRingOfDegree,
               " for toric divisorsors",
               [ IsToricDivisor ],
               
  function( divisor )
    local cox_ring, ring, points, rays, n, i, j, mons, mon;
    
    if not HasCoxRing( AmbientToricVariety( divisor )  ) then
        
        Error( "specify cox ring first\n" );
        
    fi;
    
    cox_ring := CoxRing( AmbientToricVariety( divisor ) );
    
    ring := ListOfVariablesOfCoxRing( AmbientToricVariety( divisor ) );

    if not IsBounded( PolytopeOfDivisor( divisor ) ) then
        
        Error( "list is infinite, cannot compute basis because it is not finite\n" );
        
    fi;

    points := LatticePoints( PolytopeOfDivisor( divisor ) );
    
    rays := RayGenerators( FanOfVariety( AmbientToricVariety( divisor ) ) );
    
    divisor := UnderlyingListOfRingElements( UnderlyingGroupElement( divisor ) );
    
    n := Length( rays );
    
    mons := [ ];
    
    for i in points do
        
        mon := List( [ 1 .. n ], j -> JoinStringsWithSeparator( [ ring[ j ], String( ( Sum( List( [ 1 .. Length( i ) ], m -> rays[ j ][ m ] * i[ m ] ) ) ) + divisor[ j ] ) ], "^" ) );
        
        mon := JoinStringsWithSeparator( mon, "*" );
        
        Add( mons, HomalgRingElement( mon, cox_ring ) );
        
    od;
    
    return mons;
    
end );

##
InstallMethod( CoxRingOfTargetOfDivisorMorphism,
               "for basepoint free divisors",
               [ IsToricDivisor ],
               
  function( divisor )
    
    return CoxRingOfTargetOfDivisorMorphism( divisor, TORIC_VARIETIES.CoxRingIndet );
    
end );

##
InstallMethod( RingMorphismOfDivisor,
               "for basepoint free divisors",
               [ IsToricDivisor ],
               
  function( divisor )
    local coxring, images, var_coxring;
    
    coxring := CoxRingOfTargetOfDivisorMorphism( divisor );
    
    var_coxring := CoxRing( AmbientToricVariety( divisor ) );
    
    images := MonomsOfCoxRingOfDegree( divisor );
    
    return RingMap( images, coxring, var_coxring );
    
end );
    

#################################
##
## Methods
##
#################################

##
InstallMethod( CharactersForClosedEmbedding,
               "for toric varieties.",
               [ IsToricDivisor and IsVeryAmple ],
               
  function( divisor )
    
    return BasisOfGlobalSections( divisor );
    
end );

##
RedispatchOnCondition( CharactersForClosedEmbedding, true, [ IsToricDivisor ], [ IsVeryAmple ], 0 );

##
InstallMethod( VeryAmpleMultiple,
               " for ample toric divisorsors.",
               [ IsToricDivisor and IsAmple ],
               
  function( divisor )
    
    return IntegerForWhichIsSureVeryAmple( divisor ) * divisor;
    
end );

##
RedispatchOnCondition( VeryAmpleMultiple, true, [ IsToricDivisor ], [ IsAmple ], 0 );

##
InstallMethod( VarietyOfDivisorpolytope,
               " for ample divisorsors",
               [ IsToricDivisor and IsBasepointFree ],
               
  function( divisor )
    
    return ToricVariety( PolytopeOfDivisor( divisor ) );
    
end );

##
InstallMethod( MonomsOfCoxRingOfDegree,
               " for homalg elements",
               [ IsToricVariety, IsHomalgElement ],
               
  function( vari, elem )
    local pos;
    
    if not IsIdenticalObj( Range( UnderlyingMorphism( elem ) ), ClassGroup( vari ) ) then
        
        Error( "wrong element\n" );
        
    fi;
    
    pos := UnderlyingListOfRingElements( elem );
    
    pos := CreateDivisor( pos, vari );
    
    return MonomsOfCoxRingOfDegree( pos );
    
end );

##
InstallMethod( MonomsOfCoxRingOfDegree,
               " for lists",
               [ IsToricVariety, IsList ],
               
  function( vari, lis )
    local pos, elem, mor;
    
    elem := HomalgMatrix( lis, 1, Length( lis ), HOMALG_MATRICES.ZZ );
    
    elem := HomalgMap( elem, 1 * HOMALG_MATRICES.ZZ, TorusInvariantDivisorGroup( vari ) );
    
    elem := HomalgElement( elem );

    mor := MapFromWeilDivisorsToClassGroup( vari );
    
    elem := ApplyMorphismToElement( mor, elem );
    
    return MonomsOfCoxRingOfDegree( vari, elem );
    
end );

##
InstallMethod( CoxRingOfTargetOfDivisorMorphism,
               "for toric divisors",
               [ IsToricDivisor, IsString ],
               
  function( divisor, variable )
    local nrpoints, classgroup, degrees, coxring;
    
    if not IsBasepointFree( divisor ) then
        
        Error( "no embedding in projective variety defined\n" );
        
    fi;
    
    nrpoints := Length( LatticePoints( Polytope( divisor ) ) );
    
    classgroup := 1 * HOMALG_MATRICES.ZZ;
    
    coxring := DefaultFieldForToricVarieties() * JoinStringsWithSeparator( [ variable, JoinStringsWithSeparator( [ "1", String( nrpoints ) ], ".." ) ], "_" );
    
    coxring := GradedRing( coxring );
    
    SetDegreeGroup( coxring, classgroup );
    
    degrees := List( [ 1 .. nrpoints ], i -> GeneratingElements( classgroup )[ 1 ] );
    
    SetWeightsOfIndeterminates( coxring, degrees );
    
    return coxring;
    
end );

##
InstallMethod( \+,
               "for toric divisors",
               [ IsToricDivisor, IsToricDivisor ],
               
  function( divisor1, divisor2 )
    local sum_of_divisors;
    
    if not IsIdenticalObj( AmbientToricVariety( divisor1 ), AmbientToricVariety( divisor2 ) ) then
        
        Error( "cannot add these divisors\n" );
        
        return 0;
        
    fi;
    
    sum_of_divisors := CreateDivisor( UnderlyingGroupElement( divisor1 ) + UnderlyingGroupElement( divisor2 ), AmbientToricVariety( divisor1 ) );
    
    SetClassOfDivisor( sum_of_divisors, ClassOfDivisor( divisor1 ) + ClassOfDivisor( divisor2 ) );
    
    return sum_of_divisors;
    
end );

##
InstallMethod( \-,
               "for toric divisor",
               [ IsToricDivisor , IsToricDivisor ],
               
  function( divisor1, divisor2 )
    
    return divisor1 + ( -1 ) * divisor2;
    
end );

##
InstallMethod( \*,
               "for toric divisorsors",
               [ IsInt, IsToricDivisor ],
               
  function( a, divisor )
    local divisor1;
    
    divisor1 := CreateDivisor( a * UnderlyingGroupElement( divisor ), AmbientToricVariety( divisor ) );
    
    SetClassOfDivisor( divisor1, a * ClassOfDivisor( divisor ) );
    
    return divisor1;
    
end );

##
InstallMethod( AddDivisorToItsAmbientVariety,
               "for toric divisors",
               [ IsToricDivisor ],
               
  function( divisor )
    local ambient_variety;
    
    ambient_variety := AmbientToricVariety( divisor );
    
    Add( ambient_variety!.WeilDivisors, divisor );
    
end );

##
InstallMethod( Polytope,
               "for toric divisors",
               [ IsToricDivisor ],
               
  function( divisor )
    
    return PolytopeOfDivisor( divisor );
    
end );

##
InstallMethod( \=,
               "for toric divisors",
               [ IsToricDivisor, IsToricDivisor ],
               
  function( divi1, divi2 )
    
    return UnderlyingGroupElement( divi1 ) = UnderlyingGroupElement( divi2 );
    
end );

##################################
##
## Constructors
##
##################################

##
InstallMethod( CreateDivisor,
               " for toric varieties",
               [ IsHomalgElement, IsToricVariety ],
               
  function( group_element, variety )
    local divisor, entry;
    
    divisor := rec( );
    
    ObjectifyWithAttributes(
                            divisor, TheTypeToricDivisor,
                            AmbientToricVariety, variety,
                            UnderlyingGroupElement, group_element
    );
    
    entry := ToDoListEntry( [ [ divisor, "IsAmple", true ] ], variety, "IsProjective", true );
    
    SetDescriptionOfImplication( entry, "a variety with an ample divisor is projective." );
    
    AddToToDoList( entry );
    
    entry := ToDoListEntry( [ [ variety, "IsSmooth", true ] ], divisor, "IsCartier", true );
    
    SetDescriptionOfImplication( entry, "every divisor of a smooth variety is Cartier." );
    
    AddToToDoList( entry );
    
#     entry := ToDoListEntry( [ [ variety, "IsSmooth", true ], [ divisor, "IsCartier", true ] ], divisor, "IsPrincipal", true );
#     
#     SetDescriptionOfImplication( entry, "every Cartier divisor on a smooth variety is principal." );
#     
#     AddToToDoList( entry );
    
    AddDivisorToItsAmbientVariety( divisor );
    
    return divisor;
    
end );

##
InstallMethod( CreateDivisor,
               "for toric varieties",
               [ IsList, IsToricVariety ],
               
  function( group_element, variety )
    local elem;
    
    elem := HomalgMatrix( [ group_element ], HOMALG_MATRICES.ZZ );
    
    elem := HomalgMap( elem, 1 * HOMALG_MATRICES.ZZ, TorusInvariantDivisorGroup( variety ) );
    
    elem := HomalgElement( elem );
    
    return CreateDivisor( elem, variety );
    
end );

##
InstallMethod( DivisorOfCharacter,
               " for toric varieties",
               [ IsHomalgElement, IsToricVariety ],
               
  function( character, variety )
    local group_element, divisor;
    
    group_element := ApplyMorphismToElement( MapFromCharacterToPrincipalDivisor( variety ), character );
    
    divisor := CreateDivisor( group_element, variety );
    
    SetIsPrincipal( divisor, true );
    
    SetCharacterOfPrincipalDivisor( divisor, character );
    
    SetIsCartier( divisor, true );
    
    SetCartierData( divisor, List( MaximalCones( FanOfVariety( variety ) ), i -> ( -1 )* UnderlyingListOfRingElements( character ) ) );
    
    SetClassOfDivisor( divisor, TheZeroElement( ClassGroup( variety ) ) );
    
    AddDivisorToItsAmbientVariety( divisor );
    
    return divisor;
    
end );

##
InstallMethod( DivisorOfCharacter,
               " for toric varieties.",
               [ IsList, IsToricVariety ],
               
  function( character, variety )
    
    character := HomalgMatrix( [ character ], HOMALG_MATRICES.ZZ );
    
    character := HomalgMap( character, 1 * HOMALG_MATRICES.ZZ, CharacterLattice( variety ) );
    
    character := HomalgElement( character );
    
    return DivisorOfCharacter( character, variety );
    
end );

## construct divisor associated to list encoding homalgElement in the classgroup of a toric variety
InstallMethod( DivisorOfGivenClass,
               " for toric varieties.",
               [ IsToricVariety, IsList ],
               
function( variety, list )

local epi, matrix, preimage;
    
    if not Length( list ) = Rank( ClassGroup( variety ) ) then

       Error( "Length of list does not match the rank of the class group" );

    fi;

      epi := MapFromWeilDivisorsToClassGroup( variety );
      
      # and its mapping matrix
      matrix := MatrixOfMap( epi );

      # now find solution to X * matrix = [list] by applying "RightDivide"
      preimage := RightDivide( HomalgMatrix( [list], HOMALG_MATRICES.ZZ ) , matrix );

      # turn preimage into an HomalgElement
      # the use of TorusInvariantDivisorGroup ensures that the method ClassOfDivisor is applicable to the created divisor
      preimage := HomalgElement( HomalgMap( preimage, 1 * HOMALG_MATRICES.ZZ, TorusInvariantDivisorGroup( variety ) ) );

      # and now create a Weil divisor associated to this element
      return CreateDivisor( preimage, variety );

end );

## Construct divisor associated to homalgElement in the classgroup of a toric variety
InstallMethod( DivisorOfGivenClass,
               " for toric varieties.",
               [ IsToricVariety, IsHomalgElement ],
               
function( variety, elem )

local list;

    # express elem as a list
    list := UnderlyingListOfRingElements( UnderlyingGroupElement( elem ) );    

    # and then hand the data to the above method
    return DivisorOfGivenClass( variety, list );
    
end );

#################################
##
## View
##
#################################

##
InstallMethod( ViewObj,
               "for toric divisors",
               [ IsToricDivisor ],
               
  function( divisor )
    local prin;
    
    prin := false;
    
    Print( "<A" );
    
    if HasIsAmple( divisor ) then
        
        if HasIsVeryAmple( divisor ) then
            
            if IsVeryAmple( divisor ) then
                
                Print( " very ample" );
                
            elif IsAmple( divisor ) then
                
                Print( "n ample" );
                
            fi;
            
        elif IsAmple( divisor ) then
            
            Print( "n ample" );
            
        fi;
        
    fi;
    
    if HasIsBasepointFree( divisor ) then
        
        if IsBasepointFree( divisor ) then
            
            Print( " basepoint free" );
            
        fi;
        
    fi;
    
    if HasIsPrincipal( divisor ) then
        
        if IsPrincipal( divisor ) then
            
            Print( " principal" );
            
            prin := true;
            
        fi;
        
    fi;
    
    if HasIsCartier( divisor ) then
        
        if IsCartier( divisor ) and not prin then
            
            Print( " Cartier" );
            
        fi;
        
    fi;
    
    if HasIsPrimedivisor( divisor ) then
        
        if IsPrimedivisor( divisor ) then
            
            Print( " prime" );
            
        fi;
        
    fi;
    
    Print( " divisor of a toric variety with coordinates " );
    
    ViewObj( UnderlyingGroupElement( divisor ) );
    
    Print( ">" );
    
end );

##
InstallMethod( Display,
               "for toric divisors",
               [ IsToricDivisor ],
               
  function( divisor )
    local prin;
    
    prin := false;
    
    Print( "A" );
    
    if HasIsAmple( divisor ) then
        
        if HasIsVeryAmple( divisor ) then
            
            if IsVeryAmple( divisor ) then
                
                Print( " very ample" );
                
            elif IsAmple( divisor ) then
                
                Print( "n ample" );
                
            fi;
            
        elif IsAmple( divisor ) then
            
            Print( "n ample" );
            
        fi;
        
    fi;
    
    if HasIsBasepointFree( divisor ) then
        
        if IsBasepointFree( divisor ) then
            
            Print( " basepoint free" );
            
        fi;
        
    fi;
    
    if HasIsPrincipal( divisor ) then
        
        if IsPrincipal( divisor ) then
            
            Print( " principal" );
            
            prin := true;
            
        fi;
        
    fi;
    
    if HasIsCartier( divisor ) then
        
        if IsCartier( divisor ) and not prin then
            
            Print( " Cartier" );
            
        fi;
        
    fi;
    
    Print( " divisor of a toric variety" );
    
    Print( ".\n" );
    
end );
