import socket
import asyncio
import time
import random
import json
import re
import requests
from elasticsearch import Elasticsearch

from ioc_finder import find_iocs
from walkoff_app_sdk.app_base import AppBase

class Tools(AppBase):
    """
    An example of a Walkoff App.
    Inherit from the AppBase class to have Redis, logging, and console logging set up behind the scenes.
    """
    __version__ = "1.0.0"
    app_name = "Shuffle Tools"  # this needs to match "name" in api.yaml for WALKOFF to work

    def __init__(self, redis, logger, console_logger=None):
        """
        Each app should have this __init__ to set up Redis and logging.
        :param redis:
        :param logger:
        :param console_logger:
        """
        super().__init__(redis, logger, console_logger)

    # https://github.com/fhightower/ioc-finder
    async def parse_ioc(self, input_string, input_type="all"):
        if input_type == "":
            input_type = "all"

        iocs = find_iocs(input_string)
        newarray = []
        for key, value in iocs.items():
            if input_type != "all":
                if key != input_type:
                    continue

            if len(value) > 0:
                for item in value:
                    # If in here: attack techniques. Shouldn't be 3 levels so no
                    # recursion necessary
                    if isinstance(value, dict):
                        for subkey, subvalue in value.items():
                            if len(subvalue) > 0:
                                for subitem in subvalue:
                                    data = {"data": subitem, "data_type": "%s_%s" % (key[:-1], subkey)}
                                    if data not in newarray:
                                        newarray.append(data)
                    else:
                        data = {"data": item, "data_type": key[:-1]}
                        if data not in newarray:
                            newarray.append(data)


        # Reformatting IP
        for item in newarray:
            if "ip" in item["data_type"]:
                item["data_type"] = "ip"

        try:
            newarray = json.dumps(newarray)
        except json.decoder.JSONDecodeError as e:
            return "Failed to parse IOC's: %s" % e

        return newarray

    async def parse_list(self, items, splitter="\n"):
        if splitter == "":
            splitter = "\n"

        splititems = items.split(splitter)

        return str(splititems)

    async def get_length(self, item):
        if item.startswith("[") and item.endswith("]"):
            try:
                item = item.replace("\'", "\"", -1)
                item = json.loads(item)
            except json.decoder.JSONDecodeError as e:
                print("Parse error: %s" % e) 
                pass

        return str(len(item))

    async def translate_value(self, input_data, translate_from, translate_to):
        splitdata = [translate_from]
        splitvalue = ""
        if ", " in translate_from:
            splitdata = translate_from.split(", ")
        elif "," in translate_from:
            splitdata = translate_from.split(",")

        for item in splitdata:
            input_data = input_data.replace(item, translate_to)

        return input_data

    async def execute_python(self, code, shuffle_input):
        print("Run with shuffle_data %s" % shuffle_input)
        print("And python code %s" % code)
        # Write the code to a file, then jdjd
        exec(code)

        # May be necessary
        #compile()

        return "Some return: %s" % shuffle_input

    async def parse_json(self, str_input):
        str_input = re.sub('[^A-Za-z0-9".]', '', str_input)
        list_json = str_input.split("\"\"")
        #json_object = json.loads(json_strings)
        #return (str_input.split('"src": "')[1]).split('", "http_user_agent":')[0]

        #return list_json[list_json.index("src")+1]
        json_object = {"src":list_json[list_json.index("src")+1], "time":list_json[list_json.index("reqtime")+1]}
        return json_object

    async def save_results(self, result, ref_time, analyzer_name):
        es = Elasticsearch([{'host':'10.88.200.105','port':9200}])
        res = es.index(index='results', doc_type='result', id=ref_time+analyzer_name, body=eval(result))

        return res

if __name__ == "__main__":
    asyncio.run(Tools.run(), debug=True)
