#!/usr/bin/python

# Copyright: (c) 2019, Alexandre Iooss <erdnaxe@crans.org>
# GNU General Public License v3.0+

"""
This module simulate the edition of a MoinMoin wiki page

Example:
  moinmoin_page:
    url: https://wiki.crans.org/WikiErdnaxe
    user: WikiErdnaxe
    password: HoTuNeMeConnaisPas
    content: "{{ lookup('template', 'mapage.j2') }}"
    revision_comment: Bip bip
"""

import re
import urllib.error
import urllib.parse
import urllib.request

from ansible.module_utils.basic import AnsibleModule


def login(url, user, password):
    """
    Log in and return session cookie or None if failed

    :param url: random wiki url (not root page)
    :param user: wiki user
    :param password: user's password
    :return: session cookie
    """
    # Send a HTTP POST request
    data = urllib.parse.urlencode({
        'action': 'login',
        'login': 'Connexion',
        'name': user,
        'password': password
    }).encode()
    req = urllib.request.Request(url, data)
    try:
        response = urllib.request.urlopen(req)
        cookie = response.getheader('set-cookie')
    except urllib.error.HTTPError as e:
        # If 404, then also return header
        cookie = e.getheader('set-cookie')

    # Check that authentication worked
    assert cookie, 'server did not return a session cookie'
    return cookie


def edit_ticket(url, cookie):
    """
    Return edition ticket of url

    :param url: page to edit
    :param cookie: session cookie
    :return: edit ticket
    """
    # Send request with session cookie
    suffix = "?action=edit&editor=text"
    req = urllib.request.Request(url + suffix)
    req.add_header("Cookie", cookie)
    content = urllib.request.urlopen(req).read().decode('utf-8')

    # Search for ticket
    search = re.search('name=\"ticket\" value=\"([^\"]*)\"', content)
    assert search, 'no edit ticket was found'
    return search[1]


def edit(url, user, password, content, revision_comment):
    """
    Edit a MoinMoin wiki page

    :param url: page to edit
    :param user: wiki user
    :param password: user's password
    :param content: content to place on this page
    :param revision_comment: revision comment
    """
    # Connect and get edit ticket
    cookie = login(url, user, password)
    ticket = edit_ticket(url, cookie)

    # Create request and send
    data = {
        'button_save': 'Enregistrer les modifications',
        'category': '',
        'comment': revision_comment.encode("utf-8"),
        'savetext': content.encode("utf-8"),
        'action': 'edit',
        'ticket': ticket
    }
    req = urllib.request.Request(url, urllib.parse.urlencode(data).encode())
    req.add_header("Cookie", cookie)
    urllib.request.urlopen(req)


def run_module():
    # Define arguments that should be passed
    module_args = {
        'url': {'type': 'str', 'required': True},
        'user': {'type': 'str', 'required': True},
        'password': {'type': 'str', 'required': True},
        'content': {'type': 'str', 'required': True},
        'revision_comment': {'type': 'str', 'required': True},
    }

    # Define arguments that are returned
    result = {
        'changed': False,
    }

    # Our AnsibleModule
    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True
    )

    # TODO: get current wiki page and compare
    result['changed'] = True

    # If not is check mode and page need to change, then update page
    if not module.check_mode and result['changed']:
        edit(**module.params)

    module.exit_json(**result)


def main():
    run_module()


if __name__ == '__main__':
    main()