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

# Copyright (c) 2015-2016, Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import os


from trsync.objects import RemoteLock
from trsync.objects import RsyncOps
from trsync.objects import RsyncUrl
from trsync.objects import TRsync


class TRSyncApi(object):

    def _success(self, server, message=None, force=False):
        if force:
            server['success'] = True
        server['messages'].append(message)

    def _fail(self, server, message=None):
        server['success'] = False
        server['errors'].append(message)

    def _init_serverdata(self, dests):
        """Make a serverdata object for each destiantion"""
        return [{'dest': dest,
                 'remote': None,
                 'lock': None,
                 'success': True,
                 'messages': [],
                 'errors': []}
                for dest in dests]

    def _extract_stats(self, servers):
        return dict((s['dest'], {'success': s['success'],
                                 'messages': s['messages'],
                                 'errors': s['errors']})
                    for s in servers)

    def _connect_and_lock(self, servers, repo_name, **kwargs):
        """Connect and lock each destination"""
        for s in servers:
            try:
                remote = TRsync(s['dest'], **kwargs)
                path = remote.get_repo_path(repo_name)
                lock = RemoteLock(remote, path=path, force=False)
                lock.acquire()
                s['lock'] = lock
                s['remote'] = remote
            except Exception as e:
                self._fail(s, 'Locking %s on %s: FAILED' % (path, s['dest']) +
                              "\n" + str(e))

    def _do_push(self, servers, source_url, repo_name, symlinks=[]):
        """Rsync stuff to all servers"""
        for s in servers:
            if s['remote'] is not None:
                try:
                    s['remote'].push(source_url, repo_name,
                                     symlinks=symlinks)
                    self._success(s, 'Push %s to %s: SUCCESS'
                                     % (source_url, s))
                except Exception as e:
                    self._fail(s, 'Push %s to %s: FAILED'
                                  % (source_url, s['dest']) +
                                  "\n" + str(e))

    def _release_locks(self, servers):
        """Release locks on all destinations"""
        for s in servers:
            if s['lock'] is not None:
                s['lock'].release()

    def _check_status(self, servers):
        """Check if all went well"""
        for s in servers:
            if s['success'] is False:
                return False
        return True

    def _rollback(self, servers, repo_name):
        """Undo the damage"""
        for s in servers:
            if s['remote'] is not None:
                s['remote'].undo_push(repo_name)

    def _commit(self, servers, repo_name, symlinks=[]):
        """Symlink the synced dir to where it belongs"""
        for s in servers:
            try:
                s['remote'].symlink(repo_name, symlinks=symlinks)
                self._success(s, "Symlinking SUCCESS")
            except Exception as e:
                self._fail(s, "Symlinking FAILED\n" + str(e))

    def _delete_old_snapshots(self, servers, repo_name):
        for s in servers:
            s['remote'].remove_old_snapshots(repo_name)

    def push(self, source_url, dests, **kwargs):
        symlinks = kwargs.pop('symlinks', [])
        snapshot_name = kwargs.pop('snapshot_name', '')
        source = RsyncOps(source_url)
        source_url = source.url.url_dir()
        snapshot_name = snapshot_name.strip(' /') or \
            os.path.basename(source.url.path)
        if not snapshot_name:
            raise RuntimeError("Could not infer snapshot name from source url"
                               " and snapshot_name was not provided.")

        servers = self._init_serverdata(dests)

        self._connect_and_lock(servers, snapshot_name, **kwargs)
        self._do_push(servers, source_url, snapshot_name, symlinks)

        all_ok = self._check_status(servers)
        if all_ok:
            self._commit(servers, snapshot_name, symlinks)
            self._delete_old_snapshots(servers, snapshot_name)
        else:
            self._rollback(servers, snapshot_name)
        self._release_locks(servers)

        return self._extract_stats(servers)

    def symlink(self, dests, symlinks, target, update=False,
                rsync_extra_params=""):
        for symlink in symlinks:
            if symlink.startswith('/') or symlink.startswith('../'):
                raise RuntimeError('Symlink points outside the root url: {}'
                                   .format(symlink))

        servers = self._init_serverdata(dests)
        for s in servers:
            try:
                s['remote'] = RsyncOps(s['dest'],
                                       rsync_extra_params=rsync_extra_params)
                for symlink in symlinks:
                    s['remote'].symlink(symlink, target, update=update)
                self._success(s, 'Creating symlinks %s targeted to %s on %s: '
                                 'SUCCESS' %
                              (str(symlinks), target, s['dest']))
            except Exception as e:
                self._fail(s, 'Creating symlinks %s targeted to %s on %s: '
                              'FAILED' % (str(symlinks), target, s['dest']) +
                              "\n" + str(e))
        return self._extract_stats(servers)

    def remove(self, dests, path, rsync_extra_params=""):
        servers = self._init_serverdata(dests)
        for s in servers:
            try:
                s['remote'] = RsyncOps(s['dest'],
                                       rsync_extra_params=rsync_extra_params)
                s['remote'].rm_all(path)
                self._success(s, 'Remove %s: SUCCESS' % (path))
            except Exception as e:
                self._fail(s, 'Remove %s: FAILED' % (path) +
                              "\n" + str(e))
        return self._extract_stats(servers)

    def get_target(self, symlink_url, recursive=False):
        url = RsyncUrl(symlink_url)
        remote = RsyncOps(url.root)
        return remote.symlink_target(url.path, recursive=recursive)
