#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# This file is part of Ansible
#
# Ansible 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, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible 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 Ansible.  If not, see <http://www.gnu.org/licenses/>.

ANSIBLE_METADATA = {'status': ['preview'],
                    'supported_by': 'community',
                    'version': '1.0'}

DOCUMENTATION = '''

module: pagerduty
short_description: Create PagerDuty maintenance windows
description:
    - This module will let you create PagerDuty maintenance windows
version_added: "1.2"
author:
    - "Andrew Newdigate (@suprememoocow)"
    - "Dylan Silva (@thaumos)"
    - "Justin Johns"
    - "Bruce Pennypacker"
requirements:
    - PagerDuty API access
options:
    state:
        description:
            - Create a maintenance window or get a list of ongoing windows.
        required: true
        default: null
        choices: [ "running", "started", "ongoing", "absent" ]
        aliases: []
    name:
        description:
            - PagerDuty unique subdomain.
        required: true
        default: null
        choices: []
        aliases: []
    user:
        description:
            - PagerDuty user ID.
        required: true
        default: null
        choices: []
        aliases: []
    passwd:
        description:
            - PagerDuty user password.
        required: true
        default: null
        choices: []
        aliases: []
    token:
        description:
            - A pagerduty token, generated on the pagerduty site. Can be used instead of
              user/passwd combination.
        required: true
        default: null
        choices: []
        aliases: []
        version_added: '1.8'
    requester_id:
        description:
            - ID of user making the request. Only needed when using a token and creating a maintenance_window.
        required: true
        default: null
        choices: []
        aliases: []
        version_added: '1.8'
    service:
        description:
            - A comma separated list of PagerDuty service IDs.
        required: false
        default: null
        choices: []
        aliases: [ services ]
    hours:
        description:
            - Length of maintenance window in hours.
        required: false
        default: 1
        choices: []
        aliases: []
    minutes:
        description:
            - Maintenance window in minutes (this is added to the hours).
        required: false
        default: 0
        choices: []
        aliases: []
        version_added: '1.8'
    desc:
        description:
            - Short description of maintenance window.
        required: false
        default: Created by Ansible
        choices: []
        aliases: []
    validate_certs:
        description:
            - If C(no), SSL certificates will not be validated. This should only be used
              on personally controlled sites using self-signed certificates.
        required: false
        default: 'yes'
        choices: ['yes', 'no']
        version_added: 1.5.1
'''

EXAMPLES='''
# List ongoing maintenance windows using a user/passwd
- pagerduty:
    name: companyabc
    user: example@example.com
    passwd: password123
    state: ongoing

# List ongoing maintenance windows using a token
- pagerduty:
    name: companyabc
    token: xxxxxxxxxxxxxx
    state: ongoing

# Create a 1 hour maintenance window for service FOO123, using a user/passwd
- pagerduty:
    name: companyabc
    user: example@example.com
    passwd: password123
    state: running
    service: FOO123

# Create a 5 minute maintenance window for service FOO123, using a token
- pagerduty:
    name: companyabc
    token: xxxxxxxxxxxxxx
    hours: 0
    minutes: 5
    state: running
    service: FOO123


# Create a 4 hour maintenance window for service FOO123 with the description "deployment".
- pagerduty:
    name: companyabc
    user: example@example.com
    passwd: password123
    state: running
    service: FOO123
    hours: 4
    desc: deployment
  register: pd_window

# Delete the previous maintenance window
- pagerduty:
    name: companyabc
    user: example@example.com
    passwd: password123
    state: absent
    service: '{{ pd_window.result.maintenance_window.id }}'
'''

import datetime
import base64

def auth_header(user, passwd, token):
    if token:
        return "Token token=%s" % token

    auth = base64.encodestring('%s:%s' % (user, passwd)).replace('\n', '')
    return "Basic %s" % auth

def ongoing(module, name, user, passwd, token):
    url = "https://" + name + ".pagerduty.com/api/v1/maintenance_windows/ongoing"
    headers = {"Authorization": auth_header(user, passwd, token)}

    response, info = fetch_url(module, url, headers=headers)
    if info['status'] != 200:
        module.fail_json(msg="failed to lookup the ongoing window: %s" % info['msg'])

    try:
        json_out = json.loads(response.read())
    except:
        json_out = ""

    return False, json_out, False


def create(module, name, user, passwd, token, requester_id, service, hours, minutes, desc):
    now = datetime.datetime.utcnow()
    later = now + datetime.timedelta(hours=int(hours), minutes=int(minutes))
    start = now.strftime("%Y-%m-%dT%H:%M:%SZ")
    end = later.strftime("%Y-%m-%dT%H:%M:%SZ")

    url = "https://" + name + ".pagerduty.com/api/v1/maintenance_windows"
    headers = {
        'Authorization': auth_header(user, passwd, token),
        'Content-Type' : 'application/json',
    }
    request_data = {'maintenance_window': {'start_time': start, 'end_time': end, 'description': desc, 'service_ids': service}}
    
    if requester_id:
        request_data['requester_id'] = requester_id
    else:
        if token:
            module.fail_json(msg="requester_id is required when using a token")

    data = json.dumps(request_data)
    response, info = fetch_url(module, url, data=data, headers=headers, method='POST')
    if info['status'] != 201:
        module.fail_json(msg="failed to create the window: %s" % info['msg'])

    try:
        json_out = json.loads(response.read())
    except:
        json_out = ""

    return False, json_out, True

def absent(module, name, user, passwd, token, requester_id, service):
    url = "https://" + name + ".pagerduty.com/api/v1/maintenance_windows/" + service[0]
    headers = {
        'Authorization': auth_header(user, passwd, token),
        'Content-Type' : 'application/json',
    }
    request_data = {}
    
    if requester_id:
        request_data['requester_id'] = requester_id
    else:
        if token:
            module.fail_json(msg="requester_id is required when using a token")

    data = json.dumps(request_data)
    response, info = fetch_url(module, url, data=data, headers=headers, method='DELETE')
    if info['status'] != 204:
        module.fail_json(msg="failed to delete the window: %s" % info['msg'])

    try:
        json_out = json.loads(response.read())
    except:
        json_out = ""

    return False, json_out, True


def main():

    module = AnsibleModule(
        argument_spec=dict(
        state=dict(required=True, choices=['running', 'started', 'ongoing', 'absent']),
        name=dict(required=True),
        user=dict(required=False),
        passwd=dict(required=False),
        token=dict(required=False),
        service=dict(required=False, type='list', aliases=["services"]),
        requester_id=dict(required=False),
        hours=dict(default='1', required=False),
        minutes=dict(default='0', required=False),
        desc=dict(default='Created by Ansible', required=False),
        validate_certs = dict(default='yes', type='bool'),
        )
    )

    state = module.params['state']
    name = module.params['name']
    user = module.params['user']
    passwd = module.params['passwd']
    token = module.params['token']
    service = module.params['service']
    hours = module.params['hours']
    minutes = module.params['minutes']
    token = module.params['token']
    desc = module.params['desc']
    requester_id =  module.params['requester_id']

    if not token and not (user or passwd):
        module.fail_json(msg="neither user and passwd nor token specified")

    if state == "running" or state == "started":
        if not service:
            module.fail_json(msg="service not specified")
        (rc, out, changed) = create(module, name, user, passwd, token, requester_id, service, hours, minutes, desc)
        if rc == 0:
            changed=True

    if state == "ongoing":
        (rc, out, changed) = ongoing(module, name, user, passwd, token)

    if state == "absent":
        (rc, out, changed) = absent(module, name, user, passwd, token, requester_id, service)

    if rc != 0:
        module.fail_json(msg="failed", result=out)


    module.exit_json(msg="success", result=out, changed=changed)

# import module snippets
from ansible.module_utils.basic import *
from ansible.module_utils.urls import *

if __name__ == '__main__':
    main()
