import subprocess
from os import environ
from datetime import datetime, timedelta

docker_db = subprocess.Popen(['docker-compose', 'up', 'database'], stdout=subprocess.PIPE)


def add_test_data():
    # data overview:
    # users
    users = ["Ophelia Hellmuth", "Sophia Kahl", "Samira Christmann", "Vera Gildemeister", "Ernst Henninger",
             "Pascal Lingenfelter", "Mario Freitag", "Thomas Hasselhoff"]
    user_images = ['Images/avatar' + str(i+1) + '.png' for i in range(7)]

    password = "password123#"

    def email(user):
        return user.replace(" ", "_").lower() + '@mailbox.tu-dresden.de'

    # projects
    projects = []

    def next(list, dict=True):
        if dict:
            list.append({})
        else:
            list.append([])
        return list[-1]

    proj = next(projects)
    proj['name'] = "Images and Domesticity in Slavic Literature"
    proj['leader'] = "Ophelia Hellmuth"
    proj['has_exam'] = True
    proj['is_private'] = False
    proj['attendees'] = ["Ophelia Hellmuth", "Sophia Kahl", "Samira Christmann", "Vera Gildemeister", "Ernst Henninger",
                         "Pascal Lingenfelter", "Mario Freitag", "Thomas Hasselhoff"]
    proj = next(projects)
    proj['name'] = "Drones, Management, and Venice"
    proj['leader'] = "Sophia Kahl"
    proj['has_exam'] = True
    proj['is_private'] = True
    proj['attendees'] = ["Ophelia Hellmuth", "Sophia Kahl", "Samira Christmann"]
    proj = next(projects)
    proj['name'] = "Video, Museum, and Humanities in Politics, Markets, and Society"
    proj['leader'] = "Sophia Kahl"
    proj['has_exam'] = False
    proj['is_private'] = True
    proj['attendees'] = ["Sophia Kahl", "Samira Christmann"]
    proj = next(projects)
    proj['name'] = "Zombies and Planets in Political Science"
    proj['leader'] = "Pascal Lingenfelter"
    proj['has_exam'] = False
    proj['is_private'] = False
    proj['attendees'] = ["Pascal Lingenfelter", "Mario Freitag", "Thomas Hasselhoff"]
    proj = next(projects)
    proj['name'] = "Transition, Hydrology, and Climate"
    proj['leader'] = "Ernst Henninger"
    proj['has_exam'] = True
    proj['is_private'] = True
    proj['attendees'] = ["Samira Christmann", "Vera Gildemeister", "Ernst Henninger", "Pascal Lingenfelter"]

    # join requests
    join_requests = []
    request = next(join_requests)
    request['user'] = users[4]
    request['project'] = "Drones, Management, and Venice"
    request = next(join_requests)
    request['user'] = users[5]
    request['project'] = "Drones, Management, and Venice"
    request = next(join_requests)
    request['user'] = users[6]
    request['project'] = "Drones, Management, and Venice"

    # channels
    # the sequence of channels corresponds with the project sequence
    channels = []
    start_time = datetime(2017, 2, 15)
    # chat with long messages
    chan = next(channels, dict=False)
    for i in range(10):
        message = next(chan)
        message['author'] = "Ophelia Hellmuth"
        message['content'] = "Really Long Text. " * 100
        message['date_created'] = start_time + timedelta(minutes=5)
        message = next(chan)
        message['author'] = "Sophia Kahl"
        message['content'] = "Really Long Text" * 100
        message['date_created'] = start_time + timedelta(minutes=10)
        start_time += timedelta(minutes=10)
    # chat with a lot of messages
    chan = next(channels, dict=False)
    for i in range(200):
        message = next(chan)
        message['author'] = "Samira Christmann"
        message['content'] = "Nein."
        message['date_created'] = start_time + timedelta(seconds=10)
        message = next(chan)
        message['author'] = "Sophia Kahl"
        message['content'] = "Doch."
        message['date_created'] = start_time + timedelta(seconds=20)
        start_time += timedelta(seconds=20)
    # chat with very few messages
    chan = next(channels, dict=False)
    message = next(chan)
    message['author'] = "Sophia Kahl"
    message['content'] = "Das ist die einzige Nachticht."
    message['date_created'] = start_time
    # chat with no messages
    chan = next(channels, dict=False)
    chan = next(channels, dict=False)

    # matches
    matches = [[users[0], users[1]], [users[0], users[2]], [users[0], users[3]], [users[1], users[2]],
               [users[3], users[5]]]

    # entering data
    from Models import UserModel
    from Models import ProjectModel
    from Models import ChannelModel
    from Models import PostModel
    from Models import MatchModel
    from Models import JoinRequestModel
    from Models import ImageModel
    from Models import ChatModel
    from Models.ChannelModel import get_main_channel, create_main_channel
    from app import db
    import base64
    import os

    def create_project(proj, channel):
        leader = UserModel.query.filter(UserModel.display_name == proj['leader']).first()
        project = ProjectModel(name=proj['name'], channel=channel, has_exam=proj['has_exam'],
                               project_leader=[leader],
                               is_private=proj['is_private'])
        project.attendees.extend(
            [UserModel.query.filter_by(username=username).first() for username in proj['attendees']])
        print("Project: " + str(project.id) + '  ' + project.name)
        return project

    def create_channel_posts(chan, db_channel):
        for message in chan:
            author = UserModel.query.filter_by(username=message['author']).first()
            post = PostModel(channel=db_channel, author=author, date_created=message['date_created'],
                             content=message['content'])
            db.session.add(post)
        db.session.commit()
        for post in db_channel.posts:
            print(f'post created with id: {post.id} of user with id: {post.author.id}')

    # users
    print("initialising users")
    user_models = []
    for user in users:
        u = UserModel.create(user, password, email(user))
        print(u.id)
        user_models.append(u)
    # make on user dev, one mod
    user_models[0].moderation_flags.is_developer = True
    user_models[1].moderation_flags.is_moderator = True
    [db.session.add(user) for user in user_models]
    db.session.commit()
    print("initialising user images")
    script_dir = os.path.dirname(os.path.abspath(__file__))
    for username, image_path in zip(users, user_images):
        user = UserModel.query.filter_by(username=username).first()
        file_path = os.path.join(script_dir, image_path)

        with open(file_path, "rb") as img_file:
            image_base64 = base64.b64encode(img_file.read())
            image = base64.b64decode(image_base64)
        profile_image = ImageModel(uploader=user, data=image)
        db.session.add(profile_image)
        db.session.commit()
        user.profile_pic = profile_image
        db.session.add(user)
    db.session.commit()
    print("initialising user images FINISHED")
    print("initialising users FINISHED")
    print("initialising projects")
    # channels
    print("initialising channels")
    db_channels = []
    for i in range(len(channels)):
        c = ChannelModel()
        db.session.add(c)
        db.session.commit()
        db_channels.append(c)
    print("initialising channels FINISHED")
    print("initialising channel posts")
    [create_channel_posts(chan, db_channel) for chan, db_channel in zip(channels, db_channels)]
    print("initialising channel posts FINISHED")
    # projects
    [db.session.add(channel) for channel in db_channels]
    db.session.commit()
    for proj, channel in zip(projects, db_channels):
        project = create_project(proj, channel)
        db.session.add(project)
    db.session.commit()
    print("initialising projects FINISHED")
    print("initialising join requests")
    for join_request in join_requests:
        user = UserModel.query.filter_by(username=join_request['user']).first()
        project = ProjectModel.query.filter_by(name=join_request['project']).first()
        join_request = JoinRequestModel(user=user, project=project)
        db.session.add(join_request)
    db.session.commit()
    print("initialising join requests FINISHED")
    print("initialising Matches")
    for match_users_names in matches:
        match = MatchModel()
        for username in match_users_names:
            user = UserModel.query.filter_by(username=username).first()
            match.users.append(user)
        db.session.add(match)
    db.session.commit()
    print("initialising Matches FINISHED")
    print("getting channel")
    create_main_channel()
    print(get_main_channel())
    print("getting channel FINISHED")

    # creating
    chat_channel = ChannelModel()
    db.session.add(chat_channel)
    db.session.commit()
    chat = ChatModel(channel=chat_channel)
    chat.users.append(user_models[0])
    chat.users.append(user_models[1])
    db.session.add(chat)
    db.session.commit()
    post = PostModel(channel=chat_channel, author=user_models[0], date_created=start_time + timedelta(minutes=10),
                     content='new chat message content')
    db.session.add(post)
    db.session.commit()
    print("Chat message id", post.id, ' with author: ', post.author.id)

try:
    environ['DATABASE_URL'] = "postgresql://matchinit:matchinit@localhost/matchinit"

    from app import *

    out = ""
    while "ready to accept connections" not in out:
        out = str(docker_db.stdout.readline())

    db.drop_all()
    db.create_all()

    add_test_data()

    print(f"initiated database @ {environ['DATABASE_URL']}")


finally:
    docker_db.terminate()
    pass
