#!/usr/bin/env python3
# devel.a0fs.ru -- TOOLS:SEC:aw_pw_tool -- v0.r202605.1
# devel.a0fs.ru -- TOOLS:SEC:safe_pw -- v0.r202409.2
# devel.a0fs.ru -- pwtrns.py -- v0.r202402.8

from sys import stdin, stdout, stderr
from random import seed as rnd_seed, choice as rnd_choice
from argparse import ArgumentParser
from string import ascii_letters, digits
from typing import List, Iterable, Optional
from math import ceil


### VAR
SAFECH= {
    'def': '%-=_;:+/,.@',
    'url': '-._',
}

TRDICT = {
    'f': 'а', ',': 'б', 'd': 'в', 'u': 'г', 'l': 'д', 't': 'е', '`': 'ё',
    ';': 'ж', 'p': 'з', 'b': 'и', 'q': 'й', 'r': 'к', 'k': 'л', 'v': 'м',
    'y': 'н', 'j': 'о', 'g': 'п', 'h': 'р', 'c': 'с', 'n': 'т', 'e': 'у',
    'a': 'ф', '[': 'х', 'w': 'ц', 'x': 'ч', 'i': 'ш', 'o': 'щ', 'm': 'ь',
    's': 'ы', ']': 'ъ', "'": 'э', '.': 'ю', 'z': 'я', 'F': 'А', '<': 'Б',
    'D': 'В', 'U': 'Г', 'L': 'Д', 'T': 'Е', '~': 'Ё', ':': 'Ж', 'P': 'З',
    'B': 'И', 'Q': 'Й', 'R': 'К', 'K': 'Л', 'V': 'М', 'Y': 'Н', 'J': 'О',
    'G': 'П', 'H': 'Р', 'C': 'С', 'N': 'Т', 'E': 'У', 'A': 'Ф', '{': 'Х',
    'W': 'Ц', 'X': 'Ч', 'I': 'Ш', 'O': 'Щ', 'M': 'Ь', 'S': 'Ы', '}': 'Ъ',
    '"': 'Э', '>': 'Ю', 'Z': 'Я',
}

GOODPWCH=ascii_letters + digits + ' '
SPLIT_PW_LEN = 4


### FUNC
def err(msg: str):
    for l in msg.splitlines():
        stderr.write(f'ERR: {l}\n')


def out(s: str):
    stdout.write(f'{s}\n')


def panic(code, msg):
    err(msg)
    exit(code)


def ptr_reverse(d: dict) -> dict:
    return dict([(v, k) for k, v in d.items()])


def get_args(words: Optional[List[str]]) -> Iterable[str]:
    if words and isinstance(words, (tuple, list)):
        for i in words:
            yield i.strip()
    
    else:
        for i in stdin:
            yield i.strip()

def out_res(flag: bool, word: str, tr_word: str):
    if flag:
        out(f'"{word}" -> "{tr_word}"')
    
    else:
        out(f'{tr_word}')


# ARGS
ap = ArgumentParser(
    prog='aw_pw_tool', 
    description='Инструмент для работы с паролями, их преобразованием и трансляцией'
)

ap.add_argument('-u', '--url', action='store_true', default=False,
                help='Режим фильтрации пароля от опасных для url символов'
                )

ap.add_argument('-s', '--split-passwd', action='store_true', default=False,
                help='Разделить длинный пароль на части по %s символов для удобства ввода' % SPLIT_PW_LEN
                )

ap.add_argument('-S', '--show-passwd', action='store_true', default=False,
                help='Показывать пароли до преобразования'
                )

ap.add_argument('-t', '--pwtrans', action='store_true', default=False,
                help='Режим трансляции паролей из английской в русскую раскладку')

ap.add_argument('-r', '--reverse', action='store_true', default=False, 
                help='Для трансляции паролей: переводим из русской в английскую раскладку')




ap.add_argument('word', nargs='*', help='Слово для перевода')


### DO
try:
    args = ap.parse_args()

    if args.pwtrans:
        if args.reverse:
            d = ptr_reverse(TRDICT)

        else:
            d = TRDICT

        for w in get_args(args.word):
            out_res(
                args.show_passwd, 
                w, 
                ''.join(map(lambda x: d[x] if x in d else x, w))
            )

    elif args.split_passwd:
        _flag = False
        for w in get_args(args.word):
            if _flag:
                print('=' * 10)

            if args.show_passwd:
                print(' ' * 4 + w)
                print('-' * 6)

            _cnt = 1
            _part_len = ceil(len(w) / SPLIT_PW_LEN)
            _w_start = 0
            for p in range(0, _part_len):
                _w_end = _w_start + SPLIT_PW_LEN
                print('%2s: %s' % (_cnt, w[_w_start:_w_end]))

                _w_start = _w_end
                _cnt += 1
            
            if not _flag:
                _flag = True

    else:
        # Init random generator
        rnd_seed()

        if args.url:
            cur_safe_ch = SAFECH['url']
        
        else:
            cur_safe_ch = SAFECH['def']

        GOODPWCH += cur_safe_ch

        for w in get_args(args.word):
            if len(w) == 0:
                break
                
            buf = ''
            for c in w:
                if c not in GOODPWCH:
                    c = rnd_choice(cur_safe_ch)
            
                buf += c

            out_res(
                args.show_passwd,
                w,
                buf
            )

except Exception as e:
    err(f'{type(e).__name__}: {e}')
    
except KeyboardInterrupt:
    exit()
