# -*- coding: utf-8 -*-
# Copyright 2015 OpenMarket Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .api import MatrixHttpApi
from threading import Thread
import sys
# TODO: Finish implementing this.


class MatrixClient(object):
    """ WORK IN PROGRESS
    The client API for Matrix. For the raw HTTP calls, see MatrixHttpApi.

    Usage (new user):
        client = MatrixClient("https://matrix.org")
        token = client.register_with_password(username="foobar",
            password="monkey")
        room = client.create_room("myroom")
        room.send_image(file_like_object)

    Usage (logged in):
        client = MatrixClient("https://matrix.org", token="foobar")
        rooms = client.get_rooms()  # NB: From initial sync
        client.add_listener(func)  # NB: event stream callback
        rooms[0].add_listener(func)  # NB: callbacks just for this room.
        room = client.join_room("#matrix:matrix.org")
        response = room.send_text("Hello!")
        response = room.kick("@bob:matrix.org")

    Incoming event callbacks (scopes):

        def user_callback(user, incoming_event):
            pass

        def room_callback(room, incoming_event):
            pass

        def global_callback(incoming_event):
            pass

    """

    def __init__(self, base_url, token=None):
        self.api = MatrixHttpApi(base_url, token)
        self.listeners = []
        self.rooms = {
            # room_id: Room
        }
        if token:
            self._sync()

    def register_with_password(self, username, password, limit=1):
        response = self.api.register(
            "m.login.password", user=username, password=password
        )
        self.user_id = response["user_id"]
        self.token = response["access_token"]
        self.hs = response["home_server"]
        self.api.token = self.token
        self._sync(limit)
        return self.token

    def login_with_password(self, username, password, limit=1):
        response = self.api.login(
            "m.login.password", user=username, password=password
        )
        self.user_id = response["user_id"]
        self.token = response["access_token"]
        self.hs = response["home_server"]
        self.api.token = self.token
        self._sync(limit)
        return self.token

    def create_room(self, alias=None, is_public=False, invitees=()):
        response = self.api.create_room(alias, is_public, invitees)
        return self._mkroom(response["room_id"])

    def join_room(self, room_id_or_alias):
        response = self.api.join_room(room_id_or_alias)
        room_id = (
            response["room_id"] if "room_id" in response else room_id_or_alias
        )
        return self._mkroom(room_id)

    def get_rooms(self):
        return self.rooms

    def add_listener(self, callback):
        self.listeners.append(callback)

    def listen_for_events(self, timeout=30000):
        event = self.api.event_stream(self.end, timeout)
        self.end = event["end"]
        for listener in self.listeners:
            listener(event)
        for chunk in event["chunk"]:
            if "room_id" in chunk:
                self.rooms[chunk["room_id"]].events.append(chunk)
                for listener in self.rooms[chunk["room_id"]].listeners:
                    listener(chunk)

    def listen_forever(self, timeout=30000):
        while(True):
            self.listen_for_events(timeout)

    def start_listener_thread(self, timeout=30000):
        try:
            thread = Thread(target=self.listen_forever, args=(timeout, ))
            thread.daemon = True
            thread.start()
        except:
            e = sys.exc_info()[0]
            print("Error: unable to start thread. " + str(e))

    def _mkroom(self, room_id):
        self.rooms[room_id] = Room(self, room_id)
        return self.rooms[room_id]

    def _sync(self, limit=1):
        response = self.api.initial_sync(limit)
        try:
            self.end = response["end"]
            for room in response["rooms"]:
                self._mkroom(room["room_id"])

                for chunk in room["messages"]["chunk"]:
                    self.rooms.get(room["room_id"]).events.append(chunk)

        except KeyError:
            pass


class Room(object):

    def __init__(self, client, room_id):
        self.room_id = room_id
        self.client = client
        self.listeners = []
        self.events = []

    def send_text(self, text):
        return self.client.api.send_message(self.room_id, text)

    def add_listener(self, callback):
        self.listeners.append(callback)

    def get_events(self):
        return self.events

@@ -3410,21 +3410,24 @@
         
-event
+response
  = self.
@@ -3485,21 +3485,69 @@
 d = 
-event%5B%22end%22%5D%0A
+response%5B%22end%22%5D%0A%0A        for chunk in response%5B%22chunk%22%5D:%0A    
     
@@ -3586,32 +3586,36 @@
 rs:%0A            
+    
 listener(event)%0A
@@ -3611,51 +3611,14 @@
 ner(
-event)%0A        for chunk in event%5B%22chunk%22%5D:
+chunk)
 %0A   

Send the events 1-by-1 rather than in the chunk array