#!/usr/bin/python3
#
# rfreeze - Manipulate 'ROSA Freeze' features
#
# Author: Denis Silakov <denis.silakov@rosalab.ru>
#
# Copyright (C) 2014-2015 ROSA Company
#
# Distributed under the BSD license
#

import argparse
import datetime
import os
import re
import sys
import shutil

import gettext
gettext.install('rosa-freeze')

from rosa_freeze.rosa_freeze import *
from rosa_freeze.config import Config

cfg = Config()

def parse_command_line():
    global command_line
    parser = argparse.ArgumentParser(description=_('ROSA Freeze Configuration Tool'))
#    parser.add_argument('-v', '--verbose', action='store_true', help='be verbose, display even debug messages')
#    parser.add_argument('-q', '--quiet', action='store_true', help='Do not display info messages')
    subparsers = parser.add_subparsers(title='command')

    # Enable freeze
    parser_enable = subparsers.add_parser('enable', help=_('Enable Freeze mode'))
    parser_enable.add_argument('-d', '--skip_dirs', action='store', nargs="?", help=_('Folders to be skipped, separated by colon, without leading slash (e.g., home:media:mnt)'))
    storage_group = parser_enable.add_mutually_exclusive_group()
    storage_group.add_argument('-s', '--storage', action='store', nargs="?", help=_('Device to be used as a temporary storage for filesystem modifications. '
    'By default, ROSA Freeze uses tmpfs. With this option you can specify device partinion (e.g., /dev/sda1) to be used for this purposes. '
    'Rememeber that the storage device should not contain any valuable data, since all the data on it will be removed!'))
    storage_group.add_argument('-f', '--folder', action='store', nargs="?", help=_('Folder to be used as a temporary storage for filesystem modifications. '
    'By default, ROSA Freeze uses tmpfs. With this option you can specify a folder to be used for this purposes. '
    'The folder should be a top-level one (e.g. /rosa-freeze) or be located inside a folder which is not subjected to the freeze.'))
    parser_enable.set_defaults(func=enable)

    # Disable freeze
    parser_disable = subparsers.add_parser('disable', help=_('Disable Freeze mode'))
    parser_disable.set_defaults(func=disable)

    # Get status
    parser_status = subparsers.add_parser('status', help=_('Get ROSA Freeze status'))
    parser_status.set_defaults(func=print_status)

    # Merge current system state into the original one
    parser_merge = subparsers.add_parser('merge', help=_('Merge current system state into the original one'))
    parser_merge.set_defaults(func=merge)

    # Create restore point
    parser_create_rp = subparsers.add_parser('save-point', help=_('Create restore point - save original state of the system and then merge the current system into the original one'))
    parser_create_rp.set_defaults(func=create_rp)

    # List restore points
    parser_list_rp = subparsers.add_parser('list-points', help=_('Get list of restore points which can be used for rollback'))
    parser_list_rp.set_defaults(func=list_rp)

    # Clean restore points
    parser_clean_rp = subparsers.add_parser('clean-points', help=_('Clean restore points - remove all store points starting with given one (i.e., given one and older)'))
    parser_clean_rp.add_argument('point', action='store', help=_('restore point (run "rfreeze list-points" to get possible values)'))
    parser_clean_rp.set_defaults(func=clean_rp)

    # Rollback to restore point
    parser_rollback = subparsers.add_parser('rollback', help=_('Rollback system to a given restore point'))
    parser_rollback.set_defaults(func=rollback)
    parser_rollback.add_argument('point', action='store', nargs="?", help=_('restore point (run "rfreeze list-points" to get possible values)'))

    command_line = parser.parse_args(sys.argv[1:])

'''
Wrappers for functions from rosa_freeze module that
print human-readable messages
'''
def enable():
    # Take default freeze parameters from config,
    # override with command-line settings, if any
    if command_line.skip_dirs:
        skip_dirs = command_line.skip_dirs.split(":")
    else:
        skip_dirs = cfg['freeze']['skip_dirs'].split()

    storage = cfg['freeze']['type']
    if storage == 'folder':
        folder = cfg['freeze']['folder']
    elif storage == 'tmpfs':
        folder = ""
    elif storage == 'device':
        folder = ""
        storage = cfg['freeze']['device']
    else:
        print(_("Unsupported storage type in config: ") + storage)
        exit(1)

    if command_line.storage:
        storage = command_line.storage
    elif command_line.folder:
        storage = "folder"
        folder = command_line.folder

    res = enable_freeze(skip_dirs, storage, folder)
    if res == 0:
        print(_("Freeze mode has been enabled."))
    elif res == 2:
        print(_("ROSA Freeze is already enabled."))
    elif res == 3:
        print(_("You didn't reboot computer after ROSA Freeze was disabled. Please reboot the machine first."))
    elif res == 4:
        print(_("Failed to detect UUID for the storage device ") + storage)
    elif res == 5:
        storage_mnt = os.popen("findmnt -n -o TARGET " + storage).read().rstrip()
        print(_("Storage device is already mounted at ") + storage_mnt + _(". Please make a backup of all data located on it and umount it."))
    else:
        print(_("Something went wrong when enabling freeze mode, please inform developers..."))

    exit(res)

def disable():
    res = disable_freeze()
    if res == 0:
        print(_("Freeze mode has been disabled. Please reboot your system."))
    elif res == 1:
        print(_("You don't have ROSA Freeze enabled."))
    else:
        print(_("Something went wrong when disabling freeze mode, please inform developers..."))

    exit(res)

def merge():
    res = merge_state()
    if res == 0:
        print(_("The current state of the system has been merged to the original one."))
    elif res == 1:
        print(_("You don't have ROSA Freeze enabled."))
    else:
        print(_("Something went wrong during merge, please inform developers..."))

    exit(res)

def create_rp():
    res = create_restore_point(cfg['restore_points']['folder'])
    exit(res)

def clean_rp():
    res = clean_restore_point(cfg['restore_points']['folder'], command_line.point)
    exit(res)

def list_rp():
    p = list_restore_points(cfg['restore_points']['folder'])
    if len(p) > 0:
        print(_("The following restore points are available:"))
        for point in p:
            print( "* " + point + " (" + datetime.datetime.fromtimestamp(int(point)).strftime("%Y-%m-%d %H:%M:%S") + ")" )
    else:
        print(_("No restore points are available"))
    exit(0)

def rollback():
    res = rollback_to_point(command_line.point, cfg['restore_points']['folder'])
    exit(res)


'''
Print current status of ROSA Freeze to console
'''
def print_status():
    status = get_status()
    if status == 'enabled':
        print(_("Freeze mode is enabled"))
    elif status == 'disabled':
        print(_("Freeze mode is disabled"))
    elif status == 'disabled_pending':
        print(_("Freeze mode has been disabled, but you need to reboot to work with unfrozen system"))
    else:
        print(_("INTERNAL ERROR, get_status() returned ") + status)


if __name__ == '__main__':
    parse_command_line()
    command_line.func()
