#: processes accounting transactions from text file, and prints the balance
#:
#: usage: python p.py [<options>] <file>
#: options:
#: -i : initial balance file
#: -d : date min/max/month/year
#:   examples: 2016, 2016-04, 2016-04:2016-05, 2016-04-02:2016-04-08
#:
#: can be called from any folder, and can use wrapper script p.sh
#:
#: file contains accounting transactions with format ...
from __future__ import print_function

import sys
import getopt
from datetime import datetime, timedelta

# TODO : only define in 1 place valid account types (use dict in balance)
# TODO : process more than 1 movs file
# TODO : make mov date optional
# TODO : be less strict with lenghts


class Acct :

  @staticmethod
  def usage() :
    liLine = 0
    print( "" )
    print( sys.argv[ 0 ] )
    lF = open( sys.argv[ 0 ], 'r' )
    lbFirstComm = True
    lsL = lF.readline()
    while lsL and lbFirstComm == True :
      liLine += 1
      if lsL.startswith( "#:" ) :
        print( lsL[ 3 : -1 ] )
        lsL = lF.readline()
      else :
        break
    lF.close()

  W_ACCT = 12
  W_AMOUNT = 12
  W_DATE = 10
  W_LINE = 2 * W_ACCT + W_AMOUNT + W_DATE
  W_BAL_LINE = 24

  # valid account name types prefixes
  gssTypes = ( 'S_', 'D_', 'C_', 'P_', 'F_', 'X_' )

  gsFmtYear = "%Y"
  gsFmtMonth = "%Y-%m"
  gsFmtDate = "%Y-%m-%d"
  gsFmtDateUI = "yyyy-mm-dd"


  def __init__( self ) :

    self.miMov = 0
    self.miMovAcct = 0
    self.mDictSaldo = {}
    self.mDateIni = None
    self.mDateFin = None


  @staticmethod
  def eprint( sErrorMsg ) :
    print( sErrorMsg, file=sys.stderr )


  @staticmethod
  def valAcct( sVal ) :
    liRet = 0 # OK, default
    liLen = len( sVal )
    if liLen > Acct.W_ACCT :
      liRet = 1
      Acct.eprint( 'account name %s too long (%d), max is %d' % ( sVal, liLen, Acct.W_ACCT ) )
    elif sVal[ : 2 ] not in Acct.gssTypes :
      liRet = 1
      Acct.eprint( 'account name %s not valid, must start by %s' % ( sVal, Acct.gssTypes ) )
    return liRet

  @staticmethod
  def valAmnt( sVal ) :
    liRet = 0 # OK, default
    liLen = len( sVal )
    if liLen > Acct.W_AMOUNT :
      liRet = 1
      Acct.eprint( 'amount %s too long (%d), max is %d' % ( sVal, liLen, Acct.W_AMOUNT ) )
    try :
      lfAmount = float( sVal )
    except :
      liRet = 1
      Acct.eprint( 'amount %s is not a floating point number' % ( sVal ) )