from cpp_polygon cimport *
from cpp_vertex cimport cpp_Vertex
from cpp_coefficients cimport cpp_Coefficients
from libcpp.string cimport string
from sage.rings.integer_ring import ZZ
from sage.rings.real_mpfr import RR
from sage.matrix.constructor import matrix
from sage.plot.graphics import Graphics
from sage.plot.line import line2d

cdef class Polygon:
  cdef cpp_Polygon cpp

  def __cinit__(self,str=None):
    if str==None:
      self.cpp=cpp_Polygon()
    else:
      self.cpp=cpp_Polygon(str.encode('utf-8'))

  cpdef size(self):
    return self.cpp.size()

  cpdef graph_size(self):
    return self.cpp.graph_size()

  def vertex(self,i):
    assert(i<self.graph_size())
    cdef cpp_Vertex v=self.cpp.vertex(i)
    return (v.x,v.y)

  cpdef vertices(self):
    res=[]
    cdef ng=self.cpp.graph_size()
    cdef cpp_Vertex v
    for i in range(ng):
      v=self.cpp.vertex(i)
      res.append((v.x,v.y))
    return res

  @staticmethod
  def get_coefficients():
    C=Coefficients(init=False)
    C.cpp=cpp_Polygon.get_coefficients()
    return C

  cpdef matrix_B(self):
    cdef ng=self.graph_size()
    cdef double coeff
    B=matrix(ZZ,ng)
    for i in range(ng):
      for j in range(i,ng):
        coeff=self.cpp.get_coeff_B(i,j)
        B[i,j]=int(coeff)
        B[j,i]=int(coeff)
    return B

  cpdef matrix_C(self):
    cdef ng=self.graph_size()
    cdef double coeff
    C=matrix(RR,ng)
    for i in range(ng):
      for j in range(i,ng):
        coeff=self.cpp.get_coeff_C(i,j)
        C[i,j]=coeff
        C[j,i]=coeff
    return C

  cpdef matrix_M(self):
      cdef ng=self.graph_size()
      cdef double coeff
      M=matrix(RR,ng,ng+1)
      for i in range(ng):
        for j in range(ng+1):
          M[i,j]=self.cpp.get_coeff_M(i,j)
      return M

  def fp(self):
    return self.cpp.get_fp()

  def show(self):
    B=self.matrix_B()
    V=self.vertices()
    X=[v[0] for v in V]
    Y=[v[1] for v in V]
    xmin=min(X)
    xmax=max(X)
    ymin=min(Y)
    ymax=max(Y)
    G=Graphics()
    for x in range(xmin,xmax+1):
      G+=line2d([(x,ymin),(x,ymax)],thickness=0.5,rgbcolor=(0.8,0.8,0.8),linestyle="dotted")
    for y in range(ymin,ymax+1):
      G+=line2d([(xmin,y),(xmax,y)],thickness=0.5,rgbcolor=(0.8,0.8,0.8),linestyle="dotted")
    np=self.size()
    ng=self.graph_size()
    for i in range(ng):
      for j in range(i,ng):
        if B[i,j]==1:
          if j<np and j==i+1 or (i==0 and j==np-1):
            G+=line2d([V[i],V[j]],thickness=1.2,rgbcolor=(0.8,0,0))
          else:
            G+=line2d([V[i],V[j]],thickness=0.7,rgbcolor=(0.4,0.4,1))
    G.show(axes=False,aspect_ratio=1)

def Square(l):
    sl=repr(l)
    return Polygon('u'+sl+'r'+sl+'d'+sl+'l'+sl)
