#-*- coding: utf-8 -*-

import datetime

import utils

from rsync_remote import RsyncRemote
from utils import singleton


@singleton
class TimeStamp(object):
    def __init__(self, now=None):
        # now='2015-06-18-104259'
        self.snapshot_stamp_format = r'%Y-%m-%d-%H%M%S'
        self.snapshot_stamp_regexp = r'[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{6}'

        if now is None:
            self.now = datetime.datetime.utcnow()
        else:
            self.now = datetime.datetime.strptime(now,
                                                  self.snapshot_stamp_format)
        self.snapshot_stamp = self.now.strftime(self.snapshot_stamp_format)

    def __str__(self):
        return self.snapshot_stamp

    def reinit(self, *args, **kwagrs):
        self.__init__(*args, **kwagrs)


class TRsync(RsyncRemote):
    # TODO: possible check that rsync url is exists
    def __init__(self,
                 rsync_url,
                 snapshot_dir='snapshots',
                 latest_successful_postfix='latest',
                 save_latest_days=14,
                 init_directory_structure=True,
                 timestamp=None,
                 ):
        super(TRsync, self).__init__(rsync_url)
        self.logger = utils.logger.getChild('TRsync.' + rsync_url)
        self.timestamp = TimeStamp(timestamp)
        self.logger.info('Using timestamp {}'.format(self.timestamp))
        self.snapshot_dir = self.url.a_dir(snapshot_dir)
        self.latest_successful_postfix = latest_successful_postfix
        self.save_latest_days = save_latest_days

        if init_directory_structure is True:
            self.init_directory_structure()

    def init_directory_structure(self):
        if self.url.url_type != 'path':
            server_root = RsyncRemote(self.url.root)
            return server_root.mkdir(
                self.url.a_dir(self.url.path, self.snapshot_dir)
            )

    def push(self, source, repo_name, symlinks=[], extra=None, save_diff=True):
        latest_path = self.url.a_file(
            self.snapshot_dir,
            '{}-{}'.format(self.url.a_file(repo_name),
                           self.latest_successful_postfix)
        )

        symlinks = list(symlinks)
        symlinks.insert(0, latest_path)

        snapshot_name = self.url.a_file(
            '{}-{}'.format(self.url.a_file(repo_name), self.timestamp)
        )
        repo_path = self.url.a_file(self.snapshot_dir, snapshot_name)

        extra = '--link-dest={}'.format(
            self.url.a_file(self.url.path, latest_path)
        )

        # TODO: split transaction run (push or pull), and
        # commit/rollback functions. transaction must has possibility to
        # rollback after commit for implementation of working with pool
        # of servers. should be something like this:
        #     transactions = list()
        #     result = True
        #     for server in servers:
        #         transactions.append(server.push(source, repo_name))
        #         result = result and transactions[-1].success
        #     if result is True:
        #         for transaction in transactions:
        #             transaction.commit()
        #             result = result and transactions[-1].success
        #     if result is False:
        #         for transaction in transactions:
        #             transaction.rollback()
        transaction = list()
        try:
            # start transaction
            result = super(TRsync, self).push(source, repo_path, extra)
            transaction.append(lambda p=repo_path: self.rmdir(p))
            self.logger.info('{}'.format(result))

            if save_diff is True:
                diff_file = self.tmp.get_file(content='{}'.format(result))
                diff_file_name = '{}.diff.txt'.format(repo_path)
                super(TRsync, self).push(diff_file, diff_file_name, extra)
                transaction.append(lambda f=diff_file_name: self.rmfile(f))
                self.logger.debug('Diff file {} created.'
                                  ''.format(diff_file_name))

            for symlink in symlinks:
                try:
                    tgt = [_[1] for _ in self.ls_symlinks(symlink)][0]
                    self.logger.info('Previous {} -> {}'.format(symlink, tgt))
                    undo = lambda l=symlink, t=tgt: self.symlink(l, t)
                except:
                    undo = lambda l=symlink: self.rmfile(l)
                # TODO: implement detection of target relative symlink
                if symlink.startswith(self.snapshot_dir):
                    self.symlink(symlink, snapshot_name)
                else:
                    self.symlink(symlink, repo_path)
                transaction.append(undo)

        except RuntimeError:
            self.logger.error("Rollback transaction because some of sync"
                              "operation failed")
            [_() for _ in reversed(transaction)]
            raise

        try:
            # deleting of old snapshots ignored when assessing the transaction
            # only warning
            self._remove_old_snapshots(repo_name)
        except RuntimeError:
            self.logger.warn("Old snapshots are not deleted. Ignore. "
                             "May be next time.")

        return result

    def _remove_old_snapshots(self, repo_name, save_latest_days=None):
        if save_latest_days is None:
            save_latest_days = self.save_latest_days
        if save_latest_days is None or save_latest_days is False:
            # delete all snapshots
            self.logger.info('Deletion all of the old snapshots '
                             '(save_latest_days == {})'
                             ''.format(save_latest_days))
            save_latest_days = -1
        elif save_latest_days == 0:
            # skipping deletion
            self.logger.info('Skip deletion of old snapshots '
                             '(save_latest_days == {})'
                             ''.format(save_latest_days))
            return
        else:
            # delete snapshots older than
            self.logger.info('Deletion all of the unlinked snapshots older '
                             'than {0} days (save_latest_days == {0})'
                             ''.format(save_latest_days))
        warn_date = \
            self.timestamp.now - datetime.timedelta(days=save_latest_days)
        warn_date = datetime.datetime.combine(warn_date, datetime.time(0))
        snapshots = self.ls_dirs(
            self.url.a_dir(self.snapshot_dir),
            pattern=r'^{}-{}$'.format(
                repo_name,
                self.timestamp.snapshot_stamp_regexp
            )
        )
        links = self.ls_symlinks(self.url.a_dir())
        links += self.ls_symlinks(self.url.a_dir(self.snapshot_dir))
        for s in snapshots:
            s_date = datetime.datetime.strptime(
                s,
                '{}-{}'.format(repo_name,
                               self.timestamp.snapshot_stamp_format)
            )
            s_date = datetime.datetime.combine(s_date, datetime.time(0))
            s_path = self.url.a_dir(self.snapshot_dir, s)
            if s_date < warn_date:
                s_links = [_[0] for _ in links
                           if _[1] == s
                           or _[1].endswith('/{}'.format(s))
                           ]
                if not s_links:
                    self.rmdir(s_path)
                    self.rmfile(s_path + '.target.txt')
                    self.rmfile(s_path + '.diff.txt')
                else:
                    self.logger.info('Skip deletion of "{}" because there are '
                                     'symlinks found: {}'.format(s, s_links))
            else:
                self.logger.info('Skip deletion of "{}" because it newer than '
                                 '{} days'.format(s, save_latest_days))
