#coding: utf-8
#=======================================================================================[ T_STACK ]=======
class T_STACK:
  '''Klasa stosu - struktury FILO lub LIFO.'''
  _DATA=[]									# Pojemnik na dane - zasadniczy stos.

#------------------------------------ INIT -------------------------------------------
#---============================[ __init__ ]==========================================[]
  def __init__(self,LEN=None):
    '''Inicjacja z ew. nax długością stosu LEN.'''
    self._LEN=LEN								# Zapamiętuje ograniczenie długości. None - brak.
    self._DATA=[]								# Tworzy indywidualny pojemnik na dane.

#------------------------------------ OPER -------------------------------------------
#---============================[ PUSH ]==========================================[]
  def PUSH(self,I):
    '''Kładzie element i na stos. Jeśli jest przepełnienie - zgłasza błąd.'''
    self.BREAKif_isERROR("+")							# Przerywa jeśli stos jest pełny.
    self._DATA+=[I]								# Dodaje element na wierzchu stosu (końcu listy).

#---============================[ POP ]==========================================[]
  def  POP(self):
    '''Pobiera element ze stosu. Jeśli jest pusty - zgłasza błąd.'''
    self.BREAKif_isERROR("-")							# Przerywa jeśli stos jest pusty.
    return self._DATA.pop(-1)							# Pobiera i zwraca element z wierzchu stosu (końca listy).


#------------------------------------ SIZE -------------------------------------------
#---============================[ size ]==========================================[]
  def size(self,FULL=False):
    '''Zwraca wielkość stosu. Gdy FULL - zwraca krotke: (aktualna_wielkość,max_wielkość).'''
    RES=len(self._DATA)								# Ustala aktualną wielkość stoosu.
    if FULL: 									# Ma zwrócić i wartość aktualną i maksymalną.
      return (RES,self._LEN)							# Zwraca krotke z danymi.
    return RES									# Zwraca samą wielkość stosu.

#---============================[ isEMPTY ]==========================================[]
  def isEMPTY(self):
    '''Zwraca .T.  jeśli stos jest pusty.'''
    return self.size()==0							# Zwraca .T. jeśli stos jest pusty - ma wielkość zero.

#---============================[ isFULL ]==========================================[]
  def isFULL(self):
    '''Zwraca .T.  jeśli stos jest pełny - ma już max ilość elementów.'''
    (S,M)=self.size(True)
    return S==M									# Zwraca .T. jeśli stos jest pełny - ma wielkość max.

#------------------------------------ ERRORS -------------------------------------------
#---============================[ BREAKif_isERROR ]==========================================[]
  def BREAKif_isERROR(self,DIR):
    '''Jeśli DIR="-" i stos jest pusty zgłasza błąd "STACK is EMPTY".'''
    if DIR=="-" and self.isEMPTY():
      E='STACK is EMPTY'
      print(f'{E}!')
      raise Exception(E)
    if DIR=="+" and self.isFULL():
      E='STACK OVERFLOW'
      print(f'{E}!')
      raise Exception(E)

#------------------------------------ SHOW -------------------------------------------
#---============================[ SHOW ]==========================================[]
  def SHOW(self):
    '''pokazuje w przyjazny sposób stos.'''
    print('-'*40)
    for i in range(self.size()-1,-1,-1):
      print(f'> {self._DATA[i]:4d} <')
    print('='*40)
    print(f' STACK {"not" if not self.isEMPTY() else ""} is EMPTY')
    print(f' STACK {"not" if not self.isFULL() else ""} is FULL')


#---============================[ __name__ ]==========================================[]
if __name__=="__main__":
  STACK=T_STACK(5)
  STACK.SHOW()
  for i in range(6):
    try:
      print(f'PUSH({10*i})')
      STACK.PUSH(10*i)
    except Exception as E:
      print(f'ERROR: {E}')
    STACK.SHOW()
  print('.'*100)
  for i in range(6):
    try:
      print(f'Zdjął ze stosu {STACK.POP()}')
    except Exception as E:
      print(f'ERROR: {E}')
    STACK.SHOW()




