#!/usr/bin/python
# -*- mode: python; coding: utf-8 -*-

import argparse
import contextlib
import re
import os, os.path

def pgadmin3_serv_iter(src_fd):
    is_good_section = False
    serv_item = {}
    
    def final_serv_item():
        nonlocal serv_item
        
        if 'name' in serv_item:
            yield serv_item
        
        serv_item = {}
    
    is_good_match = re.compile(r'\[Servers\/\d+\]', re.M | re.S)
    
    for line in src_fd:
        line = line.rstrip()
        
        if line.startswith('[') and line.endswith(']'):
            yield from final_serv_item()
            
            if is_good_match.fullmatch(line):
                is_good_section = True
            else:
                is_good_section = False
            
            continue
        
        if not is_good_section:
            continue
        
        def set_serv_item(prefix, field):
            if not line.startswith(prefix):
                return
            
            value = line[len(prefix):]
            
            if not value or \
                    prefix == 'Group=' and value == 'Servers':
                return
            
            serv_item[field] = value
        
        set_serv_item('Description=', 'name')
        set_serv_item('Group=', 'dir_name')
        set_serv_item('Database=', 'database')
        set_serv_item('Server=', 'host')
        set_serv_item('Port=', 'port')
        set_serv_item('Username=', 'user')
    
    yield from final_serv_item()

def make_psql_env_file(serv_item, dest_path):
    with contextlib.ExitStack() as stack:
        name = serv_item['name']
        dir_name = serv_item.get('dir_name')
        
        if dir_name is not None:
            dir_name_path = env_path = os.path.join(
                dest_path,
                dir_name.replace(os.sep, '.'),
            )
            
            try:
                os.mkdir(dir_name_path)
            except FileExistsError:
                pass
        else:
            dir_name_path = dest_path
        
        env_path = os.path.join(
            dir_name_path,
            '{}.env'.format(name.replace(os.sep, '.')),
        )
        
        if os.path.exists(env_path):
            suffix = 1
            
            while True:
                suffix += 1
                
                env_path = os.path.join(
                    dir_name_path,
                    '{}.{}.env'.format(
                        name.replace(os.sep, '.'),
                        suffix,
                    ),
                )
                
                if not os.path.exists(env_path):
                    break
        
        env_fd = stack.enter_context(open(
            env_path,
            mode='w',
            encoding='utf-8',
            newline='\n',
        ))
        
        env_fd.write('# -*- mode: sh; coding: utf-8 -*-\n\n')
        
        def write_env(field, value):
            if value is not None:
                env_fd.write('export {}=\'{}\'\n'.format(
                    field,
                    value.replace('\'', '\'\\\'\'')
                ))
            else:
                env_fd.write('unset {}\n'.format(
                    field,
                ))
        
        write_env('PGDATABASE', serv_item.get('database'))
        write_env('PGHOST', serv_item.get('host'))
        write_env('PGPORT', serv_item.get('port'))
        write_env('PGUSER', serv_item.get('user'))

def make_psql_unset(unset_path):
    with open(
                unset_path,
                mode='w',
                encoding='utf-8',
                newline='\n',
            ) as unset_fd:
        unset_fd.write('# -*- mode: sh; coding: utf-8 -*-\n\n')
        
        def write_unset(field):
            unset_fd.write('unset {}\n'.format(
                field,
            ))
        
        write_unset('PGDATABASE')
        write_unset('PGHOST')
        write_unset('PGPORT')
        write_unset('PGUSER')

def pgadmin3_to_psql(src_path, dest_path):
    with contextlib.ExitStack() as stack:
        os.mkdir(dest_path)
        
        src_fd = stack.enter_context(open(
            src_path,
            encoding='utf-8',
            errors='replace',
        ))
        
        for serv_item in pgadmin3_serv_iter(src_fd):
            make_psql_env_file(serv_item, dest_path)
        
        make_psql_unset(os.path.join(dest_path, 'unset'))

def main():
    parser = argparse.ArgumentParser()
    
    parser.add_argument(
        'src_path',
        help='path to source pgAdmin3 config file',
    )
    parser.add_argument(
        'dest_path',
        help='path to making psql directory',
    )
    
    args = parser.parse_args()
    
    pgadmin3_to_psql(args.src_path, args.dest_path)

if __name__ == '__main__':
    main()
