from base64 import b64decode
from bfs.bfs10135.errors import bfs10137
from bfs.bfs10077.bfs11041 import bfs11052, bfs11045
from datetime import date, datetime
from math import ceil, log
from os import path
from pkcs1 import rsaes_oaep
from pkcs1.keys import RsaPrivateKey
import logging
bfs10107 = logging.getLogger(__name__)
bfs10107.setLevel(logging.INFO)
bfs11056 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-/'
class bfs11055(object):
  bfs11057 = 32
  def __init__(self, bfs10214, code, bfs11061=None, encrypted_node_identifier='', bfs10211=True, is_online=True, bfs11060=False, bfs11062=None, bfs11064=None):
    self.bfs10214 = bfs10214
    self.code = code
    self.bfs11061 = bfs11061
    self.encrypted_node_identifier = encrypted_node_identifier
    self.bfs10211 = bfs10211
    self.is_online = is_online
    self.bfs11060 = bfs11060
    self.bfs11062 = bfs11062
    self.bfs11064 = bfs11064

  @property
  def bfs11063(self):
    if (not self.encrypted_node_identifier):
      return self.encrypted_node_identifier

    return self.decrypt(self.encrypted_node_identifier)

  @classmethod
  def decrypt(bfs11065, bfs11067):
    n = 126552595132100767496431298900695851144633929478317947845463894147101930730111564183119259440078050133900835449855213073742144369102834189244736695982848189036861833523332376016102290780726072320885243610990871511351145548702602510026707584848724238826408910261032648966390926399187028038467973734166869523139L
    d = 47620634886441811911279006701406234418386824768677219155850665937740218712105852942916277172463872230223057250543653350192334441406304742984336354420144630234029397102707344769401491936717749314553261859131919096126529291266317948550850549782633820140042213874431692820120174629881124487475541748108487115593L
    bfs11066 = RsaPrivateKey(n, d)
    return rsaes_oaep.decrypt(bfs11066, b64decode(bfs11067))

  def bfs11071(self, bfs11070=None):
    if (not self.bfs11060):
      return False

    return (self.bfs11062 < (date.today() if (bfs11070 is None) else bfs11070)
)

  def bfs11073(self):
    return bool(self.encrypted_node_identifier)

  def bfs11072(self, encrypted_node_identifier):
    try:
      self.decrypt(encrypted_node_identifier)
    except:
      raise ValueError(('Not a valid encrypted node identifier: %s' % encrypted_node_identifier))

    if self.bfs10211:
      self.encrypted_node_identifier = encrypted_node_identifier



class bfs11074(object):
  def __init__(self, file_path, bfs11075=None):
    if (bfs11075 is None):
      bfs11075 = []

    self.file_path = file_path
    self.bfs11075 = bfs11075

  def read(self):
    (bfs11077, key) = self.bfs11076()
    bfs11100 = bfs11102(self.bfs11075)
    bfs11101 = bfs11100.parse(bfs11077, key)
    bfs11101.bfs11061 = self.bfs11061
    return bfs11101

  def bfs11076(self):
    with open(self.file_path, 'r') as bfs11103:
      bfs11104 = bfs11103.readline().rstrip()
      key = bfs11103.readline().rstrip()
      if ((not bfs11104) or (not key)):
        raise bfs10137()

      return (bfs11104, key)


  def write(self, bfs11105):
    with open(self.file_path, 'w') as bfs11107:
      bfs11107.write((bfs11105.bfs10214 + '\n'))
      key = bfs11105.code
      if bfs11105.bfs10211:
        key += bfs11105.encrypted_node_identifier

      bfs11107.write((key + '\n'))


  def exists(self):
    return path.exists(self.file_path)

  @property
  def bfs11061(self):
    return datetime.fromtimestamp(path.getmtime(self.file_path))


class bfs11102(object):
  def __init__(self, bfs11075=None):
    if (bfs11075 is None):
      bfs11075 = []

    self.bfs11075 = bfs11075

  def parse(self, bfs11106, key):
    code = key[:bfs11055.bfs11057]
    bfs11110 = key[bfs11055.bfs11057:]
    try:
      if (code in self.bfs11075):
        return self.bfs11112(bfs11106, code, bfs11110)
      else:
        return self.bfs11111(bfs11106, code, bfs11110)

    except ValueError:
      return bfs11055(bfs11106, code, encrypted_node_identifier=bfs11110)


  def bfs11112(self, bfs11113, code, encrypted_node_identifier):
    bfs11115 = True
    is_online = True
    bfs11114 = False
    bfs11116 = None
    try:
      bfs11117 = int(code[:1])
    except ValueError:
      bfs11117 = None

    return bfs11055(bfs11113, code, None, encrypted_node_identifier, bfs11115, is_online, bfs11114, bfs11116, bfs11117)

  def bfs11111(self, bfs11121, code, encrypted_node_identifier):
    bfs11120 = bfs11122(code)
    bfs10211 = bfs11120.bfs10211
    is_online = bfs11120.is_online
    bfs11060 = bfs11120.bfs11060
    bfs11062 = bfs11120.bfs11062
    bfs11064 = bfs11120.bfs11064
    return bfs11055(bfs11121, code, None, encrypted_node_identifier, bfs10211, is_online, bfs11060, bfs11062, bfs11064)


class bfs11124:
  bfs11123 = 0
  bfs11125 = 1
  bfs11127 = 2
  bfs11126 = 3
  bfs11130 = 4
  bfs11131 = 5
  bfs11132 = 6

class bfs11122(object):
  bfs11134 = [(bfs11124.bfs11123, 5), (bfs11124.bfs11125, 1), (bfs11124.bfs11127, 1), (bfs11124.bfs11126, 1), (bfs11124.bfs11130, 7), (bfs11124.bfs11131, 4), (bfs11124.bfs11132, 5)]
  def __init__(self, code):
    self.code = code
    bfs11133 = self.bfs11135(self.code)
    self.bfs11064 = self.bfs11137(bfs11133, bfs11124.bfs11123)
    self.is_online = (self.bfs11137(bfs11133, bfs11124.bfs11125) > 0)
    self.bfs10211 = (self.bfs11137(bfs11133, bfs11124.bfs11127) > 0)
    self.bfs11060 = (self.bfs11137(bfs11133, bfs11124.bfs11126) > 0)
    bfs11062 = None
    if self.bfs11060:
      bfs11136 = (2000 + self.bfs11137(bfs11133, bfs11124.bfs11130))
      bfs11140 = self.bfs11137(bfs11133, bfs11124.bfs11131)
      bfs11141 = self.bfs11137(bfs11133, bfs11124.bfs11132)
      bfs11062 = date(bfs11136, bfs11140, bfs11141)

    self.bfs11062 = bfs11062

  def bfs11135(self, text):
    bfs11142 = 6
    assert (len(bfs11056) == (2 ** bfs11142))
    bfs11143 = ''
    for bfs11144 in text:
      bfs11146 = bfs11045(bfs11052(bfs11144, bfs11056), '01')
      while (len(bfs11146) < bfs11142):
        bfs11146 = ('0' + bfs11146)

      bfs11143 += bfs11146

    bfs11145 = (len(text) * bfs11142)
    bfs11147 = int(ceil((log(bfs11145) / log(2))))
    bfs11150 = bfs11143[:bfs11147]
    bfs11151 = bfs11052(bfs11150, '01')
    return bfs11143[bfs11147:(bfs11147 + bfs11151)]

  def bfs11137(self, bfs11152, bfs11154):
    offset = 0
    (bfs11153, bfs11155) = zip(*self.bfs11134)
    bfs11156 = bfs11153.index(bfs11154)
    for index in range(0, bfs11156):
      offset += bfs11155[index]

    if (len(bfs11152) <= offset):
      return (-1)

    return bfs11052(bfs11152[offset:(offset + bfs11155[bfs11153.index(bfs11154)])], '01')


