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

# Copyright 2010-2016 Mir Calculate. http://www.calculate-linux.org
#
#  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 pexpect
import sys
import os
import tempfile
from calculate.lib.utils.ip import check_port
from calculate.lib.utils.files import readFile

class ProfileSyncerError(Exception):
    pass

class ProfileSyncer(object):
    def __init__(self, hostname, port,  username, passwd):
        self.hostname = hostname
        self.port = port
        self.username = username
        self.passwd = passwd
        self.exitstatus = None

    def check(self):
        return check_port(self.hostname, self.port)

    def create_process(self, source, target, *params):
        self.process = pexpect.spawn('/usr/bin/rsync',
            ['--rsh=/usr/bin/ssh -o "ControlMaster no" -p{port} {username}@{hostname}'.format(
            port=self.port, hostname=self.hostname, username=self.username),
            '--info=progress2'] + list(params) + [source, target])

    def readfile(self, filename):
        tmp_fn = tempfile.mktemp()
        for i in self.sync(filename, tmp_fn):
            pass
        if self.exitstatus == 0:
            data = readFile(tmp_fn)
            if os.path.exists(tmp_fn):
                os.unlink(tmp_fn)
            return data
        raise ProfileSyncerError("Profile server not found")

    def exists(self, filename):
        env = dict(os.environ)
        env["LANG"] = "C"
        self.process = pexpect.spawn('/usr/bin/rsync',
            ['--rsh=/usr/bin/ssh -o "ControlMaster no" -p{port} {username}@{hostname}'.format(
            port=self.port, hostname=self.hostname, username=self.username),
            '--list-only',
            filename], env=env)
        i = self.process.expect(['[Pp]assword', '(\d+)%', pexpect.EOF])
        if i == 0:
            self.process.sendline("{}\n".format(self.passwd))
        self.process.wait()
        data = self.process.read()
        self.process.close()
        return "No such file or directory (2)" not in data

    def sync(self, source, target, *params):
        num = -1
        self.create_process(source, target, *params)
        while True:
            i = self.process.expect(['[Pp]assword', '(\d+)%', pexpect.EOF])
            if i == 0:
                self.process.sendline("{}\n".format(self.passwd))
            elif i == 1:
                newnum = int(self.process.match.group(1))
                if newnum > num:
                    num = newnum
                    yield newnum
            else:
                self.output = self.process.before
                self.process.close()
                self.exitstatus = self.process.exitstatus
                yield 100
                break
