#!/usr/bin/python3
#encoding:utf-8


import os
import traceback
import sys
import datetime

import cgi
import http.cookies

import re
import warnings


__config__ = {
  'log_dir_path':'log'}


def cgi_cover(page):
  info = {
    "url":os.environ["REQUEST_URI"],
    "ip":os.environ["REMOTE_ADDR"]}
  if 'HTTP_COOKIE' in os.environ:
    geted_simple_cookies = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
  else:
    geted_simple_cookies = http.cookies.SimpleCookie()
  parametrs = {}
  files = {}
  for f in cgi.FieldStorage(keep_blank_values=True).list:
    if f.filename:
      files.setdefault(f.name, []).append((f.filename,f.file.read()))
      #files.append((f.name, f.filename,f.file.read()))
    else:
      parametrs.setdefault(f.name, []).append(f.value)
  try:
    result = page(geted_simple_cookies, info, parametrs, files)
  except:
    result = {'page':'<textarea style="width:100%; height:33%;">'}
    result['page'] += 'geted_simple_cookies:%s\n' % str(geted_simple_cookies)
    result['page'] += 'parametrs:\n'+'\n'.join([key+':'+str(value) for key,value in parametrs.items()])
    result['page'] += "</textarea>"
    result['page'] += '<textarea style="width:100%; height:33%;">'
    result['page'] += traceback.format_exc()
    result['page'] += "</textarea>"
    
    index = 1
    name = os.path.join(
      __config__['log_dir_path'],
      'cgi_log_' + datetime.datetime.now().strftime('%Y%m%d%H%M%S%f') + '_1')
    while os.path.exists(name+ '.txt'):
        index += 1
        name = '_'.join(name.split('_')[:-1])+ '_'+str(index)
    savefile = open(name + '.txt', 'w', encoding="utf-8")
    savefile.write(result['page'])
    savefile.close()
  if 'cookies' in result:
    if len(result['cookies']) != 0:
      print(result['cookies'])
  if 'content-type' in result:
    if result['content-type'].split('\n') == 1:
      print("Content-type: %s; charset=UTF-8\r\n" % result['content-type'])
    else:
      print(result['content-type'])
  else:
    print("Content-type: text/html; charset=UTF-8\r\n")
  if isinstance(result['page'], str):
    print(result['page'])
  else:
    sys.stdout.flush()
    bstdout = open(sys.stdout.fileno(), 'wb', closefd=False)
    bstdout.write(result['page'].read())
    bstdout.flush()

  """
  else:
    print("Content-type: text/html; charset=UTF-8\r\n")
    print(str(result))
  """


def template(text, param, start='${', end='}'):
  if not isinstance(text, str):
    raise Exception('Error: template text not str')
  if isinstance(param, dict):
    for index, (key, value) in enumerate(param.items()):
      if not isinstance(key, str) or not isinstance(value, str):
        try:
          raise Exception('Error: template param key or value not str', str([key, value]))
        except:
          if not isinstance(key, str):
            raise Exception('Error: template param key not str', str(index))
          elif not isinstance(value, str):
            raise Exception('Error: template param value not str', str(index))
  else:
    raise Exception('Error: template param not dict')
  text_set = set(re.findall(re.escape(start)+'[\w_ а-яА-ЯёЁ]+'+re.escape(end), text))
  param_set = set([start+key+end for key in param.keys()])
  if len(text_set ^ param_set) > 0:
    name = os.path.join(
      __config__['log_dir_path'],
      'template_log_' + datetime.datetime.now().strftime('%Y%m%d%H%M%S%f') + '_1')
    index = 0
    while os.path.exists(name+ '.txt'):
        index += 1
        name = '_'.join(name.split('_')[:-1])+ '_'+str(index)
    savefile = open(name + '.txt', 'w', encoding='utf8')
    savefile.write('text_set:\n')
    savefile.write(str(sorted(text_set)))
    savefile.write('\nparam_set:\n')
    savefile.write(str(sorted(param_set)))
    savefile.write('\ndiferents:\n')
    savefile.write(str(sorted(text_set ^ param_set)))
    savefile.write('\ntext:\n')
    savefile.write(str(text))
    savefile.close()
    warnings.warn(
      "Count of placeholder in text not equal with parametrs count",
      Warning)
  #processing
  for key, value in param.items():
    text = text.replace(start+key+end, value)
  return text
