#!/usr/bin/env python3

import argparse
import requests

from ztl.core.server import TaskServer
from ztl.core.protocol import State, Task
from ztl.core.task import ExecutableTask, TaskExecutor, TaskController


class HTTPSPostTask(ExecutableTask):

  def __init__(self, remote, request):
    self.headers = {'Content-Type': 'application/json'}
    self.remote = remote
    self.request = request

  def execute(self):
    response = requests.post(self.remote, headers=self.headers, json=self.request, verify=False)
    response.raise_for_status()
    return response.json()

  def abort(self):
    return False


class Controller(TaskController):

  def __init__(self, remote):
    self.current_id = 0
    self.running = {}
    self.remote = remote

  def init(self, request):
    self.current_id += 1
    request = Task.decode(request)
    self.running[self.current_id] = TaskExecutor(HTTPSPostTask, self.remote, request)
    return self.current_id, "Initiated task '%s' with request: %s" % (self.current_id, request)

  def status(self, mid, request):
    if mid in self.running:
      state = self.running[mid].state()
      return state, self.running[mid].result()
    else:
      return State.REJECTED, "Invalid ID '%s'" % mid

  def abort(self, mid, request):
    if mid in self.running:
      success = self.running[mid].stop()
      state = self.running[mid].state()
      return state, success
    else:
      return State.REJECTED, "Invalid ID '%s'" % mid

def main_cli():

  parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
  parser.add_argument("-p", "--port", type=int,
                      help="The port on the local machine that the server should listen to.", required=True)
  parser.add_argument("-s", "--scope", type=str,
                      help="The scope that the server should respond to.", required=True)
  parser.add_argument("-r", "--remote", type=str,
                      help="The remote server address.", required=True)

  args, unknown = parser.parse_known_args()

  server = TaskServer(args.port)
  server.register(args.scope, Controller(args.remote))
  server.listen()

if __name__ == "__main__":

  main_cli()
