"""
Module for jenkinsapi Views
"""

import logging
import json
from jenkinsapi.view import View
from jenkinsapi.custom_exceptions import JenkinsAPIException

log = logging.getLogger(__name__)


class Views(object):

    """
    An abstraction on a Jenkins object's views
    """
    LIST_VIEW = 'hudson.model.ListView'
    NESTED_VIEW = 'hudson.plugins.nested_view.NestedView'
    CATEGORIZED_VIEW = \
        'org.jenkinsci.plugins.categorizedview.CategorizedJobsView'
    MY_VIEW = 'hudson.model.MyView'
    DASHBOARD_VIEW = 'hudson.plugins.view.dashboard.Dashboard'
    PIPELINE_VIEW = ('au.com.centrumsystems.hudson.'
                     'plugin.buildpipeline.BuildPipelineView')

    def __init__(self, jenkins):
        self.jenkins = jenkins
        self._data = None

    def poll(self, tree=None):
        self._data = self.jenkins.poll(tree='views[name,url]'
                                       if tree is None else tree)

    def __len__(self):
        return len(self.keys())

    def __delitem__(self, view_name):
        if view_name == 'All':
            raise ValueError('Cannot delete this view: %s' % view_name)

        if view_name in self:
            self[view_name].delete()
            self.poll()

    def __setitem__(self, view_name, job_names_list):
        new_view = self.create(view_name)
        if isinstance(job_names_list, str):
            job_names_list = [job_names_list]
        for job_name in job_names_list:
            if not new_view.add_job(job_name):
                # Something wrong - delete view
                del self[new_view]
                raise TypeError('Job %s does not exist in Jenkins' % job_name)

    def __getitem__(self, view_name):
        self.poll()
        for row in self._data.get('views', []):
            if row['name'] == view_name:
                return View(row['url'], row['name'], self.jenkins)

        raise KeyError('View %s not found' % view_name)

    def iteritems(self):
        """
        Get the names & objects for all views
        """
        self.poll()
        for row in self._data.get('views', []):
            name = row['name']
            url = row['url']

            yield name, View(url, name, self.jenkins)

    def __contains__(self, view_name):
        """
        True if view_name is the name of a defined view
        """
        return view_name in self.keys()

    def iterkeys(self):
        """
        Get the names of all available views
        """
        self.poll()
        for row in self._data.get('views', []):
            yield row['name']

    def keys(self):
        """
        Return a list of the names of all views
        """
        return list(self.iterkeys())

    def create(self, view_name, view_type=LIST_VIEW, config=None):
        """
        Create a view
        :param view_name: name of new view, str
        :param view_type: type of the view, one of the constants in Views, str
        :param config: XML configuration of the new view
        :return: new View obj or None if view was not created
        """
        log.info('Creating "%s" view "%s"', view_type, view_name)

        if view_name in self:
            log.warning('View "%s" already exists', view_name)
            return self[view_name]

        url = '%s/createView' % self.jenkins.baseurl

        if view_type == self.CATEGORIZED_VIEW:
            if not config:
                raise JenkinsAPIException(
                    'Job XML config cannot be empty for CATEGORIZED_VIEW')

            params = {'name': view_name}

            self.jenkins.requester.post_xml_and_confirm_status(
                url,
                data=config,
                params=params)
        else:
            headers = {'Content-Type': 'application/x-www-form-urlencoded'}
            data = {
                "name": view_name,
                "mode": view_type,
                "Submit": "OK",
                "json": json.dumps({"name": view_name, "mode": view_type})
            }

            self.jenkins.requester.post_and_confirm_status(
                url,
                data=data,
                headers=headers)

        self.poll()
        return self[view_name]
