#!/usr/bin/env python
# vim: ai ts=4 sts=4 et sw=4
#
# Copyright (C) 2010, 2011, 2012, 2013, 2014 Intel, Inc.
#
#    This program is free software; you can redistribute it and/or
#    modify it under the terms of the GNU General Public License
#    as published by the Free Software Foundation; version 2 of the License.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
"""
Snapshot and Prerelease classes.
"""

import os
from datetime import datetime

from common.backenddb import BackendDBError
from common.backenddb import EntityError


class SnapshotError(Exception):
    """Local error exception."""
    pass


class Prerelease(object):
    """Handle prerelease meta data."""

    def __init__(self, snapshot, base_url, tstamp, buildid=None):
        self.snapshot = snapshot
        self.base_url = base_url
        self.tstamp = tstamp
        if buildid:
            self.buildid = buildid
            self.snap_buildid = '%s_%s' % (self.snapshot.repo['Release'], self.buildid)
        else:
            self.buildid = None
            self.snap_buildid = None

    @property
    def build_id(self):
        """Prerelease build id."""
        if self.buildid:
            return '%s_%s.%s' % (self.snapshot.repo['Release'], self.buildid, self.tstamp)
        else:
            return '%s.%s' % (self.snapshot.build_id, self.tstamp)

    @property
    def dir(self):
        """Prerelease directory."""
        if self.snapshot.repo['PrereleaseDir']:
            if self.snap_buildid:
                return os.path.join(self.snapshot.repo['PrereleaseDir'],
                                    self.snap_buildid)
            else:
                return os.path.join(self.snapshot.repo['PrereleaseDir'],
                                    self.snapshot.build_id)
        else:
            return False

    @property
    def path(self):
        """Prerelease path."""
        return os.path.join(self.snapshot.base_path, self.dir)

    @property
    def snapshot_path(self):
        """Prerelease snapshot path."""
        if self.buildid:
            """Snapshot path."""
            return "%s_%s" %(os.path.join(self.snapshot.base_path,
                                          self.snapshot.repo['SnapshotDir'],
                                          self.snapshot.repo['Release']),
                             self.buildid)
        else:
            """Snapshot path."""
            return os.path.join(self.snapshot.base_path,
                                self.snapshot.repo['SnapshotDir'],
                                self.snapshot.build_id)

    def pkg_urls(self, repo):
        """List of package(repository) urls for prerelease."""
        pkg_urls = {}
        for arch in self.snapshot.archs(repo):
            pkg_urls[arch] = os.path.join(self.base_url, self.dir,
                                          self.build_id, 'repos',
                                          repo,
                                          'packages')
        return pkg_urls

class Trbs(object):
    """Handle trbs meta data."""

    def __init__(self, snapshot, base_url, tstamp, buildid):
        self.snapshot = snapshot
        self.base_url = base_url
        self.tstamp = tstamp
        self.buildid = buildid
        self.snap_buildid = '%s_%s' % (self.snapshot.repo['Release'], self.buildid)

    @property
    def build_id(self):
        """Trbs build id."""
        return '%s_%s.%s' % (self.snapshot.repo['Release'], self.buildid, self.tstamp)

    @property
    def dir(self):
        """Trbs directory."""
        if self.snapshot.repo['PrereleaseDir']:
            return os.path.join(self.snapshot.repo['PrereleaseDir'].replace(
                                'prerelease','trbs'),
                                self.snap_buildid)
        else:
            return False

    @property
    def path(self):
        """Trbs path."""
        return os.path.join(self.snapshot.base_path, self.dir)

    def pkg_urls(self, repo):
        """List of package(repository) urls for trbs."""
        pkg_urls = {}
        for arch in self.snapshot.archs(repo):
            pkg_urls[arch] = os.path.join(self.base_url, self.dir,
                                          self.build_id, 'repos',
                                          repo,
                                          'packages')
        return pkg_urls

class Snapshot(object):
    """Snapshot maintenance class."""

    def __init__(self, backenddb, base_path, repo_name=None,
                 obs_project=None):
        """Get snapshot properties from backend db. Init snapshot attributes."""
        self.backenddb = backenddb
        self.base_path = base_path
        self.repo_name = repo_name or backenddb.get_obs_repo_map()[obs_project]
        try:
            self.repo = backenddb.get_repos()[self.repo_name]
        except BackendDBError, err:
            raise SnapshotError("Can't get info for repo '%s' : %s" \
                                % (repo_name, str(err)))

        if os.getenv('GBSFULLBUILD_SNAPSHOT') == '1':
            self.repo['SnapshotDir'] = self.repo['SnapshotDir'].replace('snapshots/','snapshots/'+os.getenv('GBSFULLBUILD_DL_POSTFIX')+'/')
        # Sanity check
        for key in ('Release', 'SnapshotDir', 'Targets'):
            if key not in self.repo:
                raise SnapshotError("Key '%s' doesn't exist for repo '%s' "\
                                    "in Redis" % (key, self.repo_name))

    @property
    def build_id(self):
        """Snapshot build id."""
        return '%s_%s' % (self.repo['Release'], self.release_id)

    @property
    def release_id(self):
        """Snapshot release id."""
        try:
            return self.backenddb.get_release_ids()[self.repo_name]
        except BackendDBError, err:
            raise SnapshotError("Can't get release info for '%s' : %s" \
                                % (self.repo_name, str(err)))

    @release_id.setter
    def release_id(self, value):
        """Setter for release_id property."""
        try:
            ids = self.backenddb.get_release_ids()
            ids[self.repo_name] = value
        except BackendDBError, err:
            raise SnapshotError("Can't set release_id %s for '%s' : %s" \
                                % (value, self.repo_name, str(err)))

    @property
    def dir(self):
        """Snapshot directory."""
        return self.repo['SnapshotDir']

    @property
    def path(self):
        """Snapshot path."""
        return os.path.join(self.base_path,
                            self.repo['SnapshotDir'],
                            self.build_id)

    @property
    def targets(self):
        """List of targets enabled in snapshot."""
        return self.repo['Targets']

    def archs(self, repo):
        """List of architectures used in snapshot
        """
        for target in self.targets:
            if str(target['Name']) != repo:
                continue
            return target['Architectures']

    def inc(self):
        """Increment stapshot."""
        try:
            sdtime, snum = self.release_id.split('.')
        except EntityError:
            sdtime = None
            snum = 0

        cdtime = datetime.now().strftime("%Y%m%d")
        if sdtime == cdtime:
            # datetime is the same - increment the number
            self.release_id = '%s.%d' % (cdtime, int(snum)+1)
        else:
            # datetime changed - set number to 1
            self.release_id = '%s.1' % cdtime

    def get_prerelease(self, base_url, tstamp, buildid=None):
        """Factory for Prerelease object."""
        return Prerelease(self, base_url, tstamp, buildid)

    def get_trbs(self, base_url, tstamp, buildid):
        """Factory for trbs object."""
        return Trbs(self, base_url, tstamp, buildid)

def snapshot_project_enabled(backenddb, obs_project):
    """Check if project is enabled for OBS project.
       This is done by querying repo name from Redis
       return the True if repo name exists,otherwise
       return False
    """
    try:
        # pylint: disable=W0612
        # disable unused variable
        repo_name = backenddb.get_obs_repo_map()[obs_project]
        # pylint: enable=W0612
        return True
    except (BackendDBError, EntityError), err:
        print err
        return False
