#!/usr/bin/env python3

import argparse
from data_printer import p
from python_perl_storable import freeze, thaw
import sys
import re
import struct


parser = argparse.ArgumentParser(description='Упаковка-распаковка данных питон в/из формат(а) Perl Storable')


sub_parser = parser.add_subparsers(dest='command', help='Подкоманды')

parser_freeze = sub_parser.add_parser('freeze', help='Заморозка')
parser_freeze.add_argument('--data', '-d', dest="data",
	default=None,
	help='Строка данных на языке питон. Если не указана - берётся из STDIN')
parser_freeze.add_argument('--iconv', '-i', dest="iconv",
	default=None,
	help='Кодировка для строк')
parser_freeze.add_argument('--as-binary', '-b', dest="as_binary",
	action='store_true',
	help='Выводит как есть - в бинарном виде')
parser_freeze.add_argument('--as-string', '-s', dest="as_string",
	action='store_true',
	help='Выводит как bytes python3 без подсветки')
parser_freeze.add_argument('--magic', '-m', dest='magic', 
	action='store_true',
	help='Добавить к выводу магическое число')


parser_thaw = sub_parser.add_parser('thaw', help='Разморозка')
parser_thaw.add_argument('--data', '-d', dest="data",
	default=None,
	help='Бинарная строка в формате Storable. Если не указана - берётся из STDIN')
parser_thaw.add_argument('--iconv', '-i', dest="iconv",
	default=None,
	help='Кодировка для строк')
parser_thaw.add_argument('--as-binary', '-b', dest="as_binary",
	action='store_true',
	help='Данные в бинарном виде')
parser_thaw.add_argument('--as-string', '-s', dest="as_string",
	action='store_true',
	help='Вывод структуры без подсветки')


UNCOLOR = re.compile(r'\x1b\[[\d;]+?m')
def uncolor(data):
	return UNCOLOR.sub('', data)
	

args = parser.parse_args()

try:

	if args.command == 'freeze':
		if args.as_string and args.as_binary:
			print("-b и -s не могут быть использованы одновременно", 
				file=sys.stderr)
			exit(1)

		x = freeze(
			eval(args.data, {}, {}) 
				if args.data is not None 
				else sys.stdin.read(),
			magic=args.magic,
			iconv=((lambda s: s.encode(args.iconv)) if args.iconv else None)
		)

		if args.as_string:
			print(x)
		elif args.as_binary:
			sys.stdout.buffer.write(x)
		else:
			p(x)

	elif args.command == 'thaw':
		data = args.data if args.data is not None else sys.stdin.buffer.read()
		if args.as_binary:
			pass
		else:
			if isinstance(data, bytes):
				data = data.decode('utf-8')
			data = eval(uncolor(data), {}, {})
		
		x = thaw(data, iconv=((lambda s: s.decode(args.iconv)) if args.iconv else None))
		p(x, color=not args.as_string)
	else:
	    parser.print_usage()
except struct.error as e:
	print("Структура повреждена: " + str(e), file=sys.stderr)
