import os
import logging
from json import loads, dumps
from datetime import timedelta
from argparse import ArgumentParser

from redis import Redis
from flask import Response, Flask, request

app = Flask(__name__)
log = logging.getLogger(__name__)

parser = ArgumentParser()
parser.add_argument("-a", "--address",
                    action="store", dest="address",
                    type=str, required=True,
                    help="Address for api")
parser.add_argument("-p", "--port",
                    action="store", dest="port",
                    type=str, required=True,
                    help="Port for api")
parser.add_argument("-c", "--crt",
                    action="store", dest="cert",
                    type=str, required=False,
                    help="Path to certificate for this API")
parser.add_argument("-k", "--key",
                    action="store", dest="key",
                    type=str, required=False,
                    help="Path to key of certificate used by this API")

parser.add_argument("-rp", "--redis-port",
                    action="store", dest="redis-port",
                    type=str, required=True,
                    help="Port for Redis client")

args = vars(parser.parse_args())

api_address = args["address"]
api_port = args["port"]
api_cert = args["cert"]
api_key = args["key"]

redis_port = args["redis-port"]
r = Redis(port=redis_port, charset="utf-8", decode_responses=True)


@app.route("/hash", methods=['POST'])
def create_redis_hash():
    data = loads(request.data)
    success = r.hmset(data["key"], data["pairs"])
    if data.get("expire") is not None:
      expiration = timedelta(**data.get("expire"))
      r.expire(data["key"], expiration)
    
    response_body = {"success": success}
    response_body[data["key"]] = r.hgetall(data["key"])
  
    return Response(dumps(response_body), status=200, mimetype="application/json")


@app.route("/hash", methods=['PUT'])
def update_redis_hash():
    data = loads(request.data)
    success = r.hmset(data["key"], data["pairs"])
    if data.get("expire") is not None:
      expiration = timedelta(**data.get("expire"))
      r.expire(data["key"], expiration)
    
    if data.get("newkey") is not None:
      r.rename(data["key"], data["newkey"])

    response_body = {"success": success}
    if data.get("newkey") is not None:
      response_body[data["newkey"]] = r.hgetall(data["newkey"])
    else:
      response_body[data["key"]] = r.hgetall(data["key"])
  
    return Response(dumps(response_body), status=200, mimetype="application/json")


@app.route("/hash", methods=['GET'])
def get_redis_hash():
    response_body = {"success": True}
    key = request.headers.get("key")
    response_body[key] = r.hgetall(key)

    return Response(dumps(response_body), status=200, mimetype="application/json")


@app.route("/key", methods=['DELETE'])
def delete_redis_key():
    status = 200
    key = request.headers.get("key")
    success = r.delete(key)

    if not success:
        status = 404
    response_body = {"success": bool(success)}

    return Response(dumps(response_body), status=status, mimetype="application/json")


@app.route("/list", methods=['POST'])
def create_redis_list():
    data = loads(request.data)
    strat = data.get("strategy")
    if strat is not None and strat == "left":
      length = r.lpush(data["key"], *data["values"])
    else:
      length = r.rpush(data["key"], *data["values"])
   
    response_body = {"length": length}
    response_body[data["key"]] = r.lrange(data["key"], 0, -1)
  
    return Response(dumps(response_body), status=200, mimetype="application/json")


@app.route("/list", methods=['GET'])
def get_entire_list():
    response_body = {"success": True}
    key = request.headers.get("key")
    response_body[key] = r.lrange(key, 0, -1) 

    return Response(dumps(response_body), status=200, mimetype="application/json")


@app.route("/list/<idx>", methods=['GET'])
def get_list_at_idx(idx):
    response_body = {"success": True}
    key = request.headers.get("key")
    response_body[key] = {}
    response_body[key][str(idx)] = r.lindex(key, idx) 

    return Response(dumps(response_body), status=200, mimetype="application/json")


@app.route("/set", methods=['POST'])
def create_add_set():
    data = loads(request.data)
    length = r.sadd(data["key"], *data["values"])
   
    response_body = {"length": length}
    response_body[data["key"]] = list(r.smembers(data["key"]))
  
    return Response(dumps(response_body), status=200, mimetype="application/json")


@app.route("/set/<n_items>", methods=['GET'])
def get_n_items_set(n_items):
    response_body = {"success": True}
    key = request.headers.get("key")
   
    response_body = {key: list(r.srandmember(key, n_items))}
  
    return Response(dumps(response_body), status=200, mimetype="application/json")


@app.route("/set", methods=['GET'])
def get_set():
    response_body = {"success": True}
    key = request.headers.get("key")
   
    response_body = {key: list(r.smembers(key))}
  
    return Response(dumps(response_body), status=200, mimetype="application/json")


def start_api(address, port, clnt_cert=None, clnt_key=None):
    if clnt_cert is None or clnt_key is None:
      app.run(host=address, port=port, debug=False)
    else:
      app.run(host=address, port=port, 
              ssl_context=(clnt_cert, clnt_key), debug=False)

if api_cert is None or api_key is None: 
  start_api(api_address, api_port)
else:
  start_api(api_address, api_port, api_cert, api_key)


[((10, 6, 10, 21), 'flask.Flask', 'Flask', ({(10, 12, 10, 20): '__name__'}, {}), '(__name__)', False, 'from flask import Response, Flask, request\n'), ((11, 6, 11, 33), 'logging.getLogger', 'logging.getLogger', ({(11, 24, 11, 32): '__name__'}, {}), '(__name__)', False, 'import logging\n'), ((13, 9, 13, 25), 'argparse.ArgumentParser', 'ArgumentParser', ({}, {}), '()', False, 'from argparse import ArgumentParser\n'), ((44, 4, 44, 66), 'redis.Redis', 'Redis', (), '', False, 'from redis import Redis\n'), ((49, 11, 49, 30), 'json.loads', 'loads', ({(49, 17, 49, 29): 'request.data'}, {}), '(request.data)', False, 'from json import loads, dumps\n'), ((63, 11, 63, 30), 'json.loads', 'loads', ({(63, 17, 63, 29): 'request.data'}, {}), '(request.data)', False, 'from json import loads, dumps\n'), ((84, 10, 84, 36), 'flask.request.headers.get', 'request.headers.get', ({(84, 30, 84, 35): '"""key"""'}, {}), "('key')", False, 'from flask import Response, Flask, request\n'), ((93, 10, 93, 36), 'flask.request.headers.get', 'request.headers.get', ({(93, 30, 93, 35): '"""key"""'}, {}), "('key')", False, 'from flask import Response, Flask, request\n'), ((105, 11, 105, 30), 'json.loads', 'loads', ({(105, 17, 105, 29): 'request.data'}, {}), '(request.data)', False, 'from json import loads, dumps\n'), ((121, 10, 121, 36), 'flask.request.headers.get', 'request.headers.get', ({(121, 30, 121, 35): '"""key"""'}, {}), "('key')", False, 'from flask import Response, Flask, request\n'), ((130, 10, 130, 36), 'flask.request.headers.get', 'request.headers.get', ({(130, 30, 130, 35): '"""key"""'}, {}), "('key')", False, 'from flask import Response, Flask, request\n'), ((139, 11, 139, 30), 'json.loads', 'loads', ({(139, 17, 139, 29): 'request.data'}, {}), '(request.data)', False, 'from json import loads, dumps\n'), ((151, 10, 151, 36), 'flask.request.headers.get', 'request.headers.get', ({(151, 30, 151, 35): '"""key"""'}, {}), "('key')", False, 'from flask import Response, Flask, request\n'), ((161, 10, 161, 36), 'flask.request.headers.get', 'request.headers.get', ({(161, 30, 161, 35): '"""key"""'}, {}), "('key')", False, 'from flask import Response, Flask, request\n'), ((58, 20, 58, 40), 'json.dumps', 'dumps', ({(58, 26, 58, 39): 'response_body'}, {}), '(response_body)', False, 'from json import loads, dumps\n'), ((78, 20, 78, 40), 'json.dumps', 'dumps', ({(78, 26, 78, 39): 'response_body'}, {}), '(response_body)', False, 'from json import loads, dumps\n'), ((87, 20, 87, 40), 'json.dumps', 'dumps', ({(87, 26, 87, 39): 'response_body'}, {}), '(response_body)', False, 'from json import loads, dumps\n'), ((100, 20, 100, 40), 'json.dumps', 'dumps', ({(100, 26, 100, 39): 'response_body'}, {}), '(response_body)', False, 'from json import loads, dumps\n'), ((115, 20, 115, 40), 'json.dumps', 'dumps', ({(115, 26, 115, 39): 'response_body'}, {}), '(response_body)', False, 'from json import loads, dumps\n'), ((124, 20, 124, 40), 'json.dumps', 'dumps', ({(124, 26, 124, 39): 'response_body'}, {}), '(response_body)', False, 'from json import loads, dumps\n'), ((134, 20, 134, 40), 'json.dumps', 'dumps', ({(134, 26, 134, 39): 'response_body'}, {}), '(response_body)', False, 'from json import loads, dumps\n'), ((145, 20, 145, 40), 'json.dumps', 'dumps', ({(145, 26, 145, 39): 'response_body'}, {}), '(response_body)', False, 'from json import loads, dumps\n'), ((155, 20, 155, 40), 'json.dumps', 'dumps', ({(155, 26, 155, 39): 'response_body'}, {}), '(response_body)', False, 'from json import loads, dumps\n'), ((165, 20, 165, 40), 'json.dumps', 'dumps', ({(165, 26, 165, 39): 'response_body'}, {}), '(response_body)', False, 'from json import loads, dumps\n')]