// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package examples.baku.io.permissions.messenger;

import android.provider.ContactsContract;
import android.widget.NumberPicker;

import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseException;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.ValueEventListener;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Created by phamilton on 6/28/16.
 *
 * !!!!!!!!!FOR PROTOTYPING ONLY!!!!!!!
 * Messaging on top of Firebase real-time database.
 * Handles single target messaging only.
 * Stand in for something like socket.io.
 */
public class Messenger implements ChildEventListener {

    static final String KEY_TARGET = "target";

    static final String KEY_GROUPS = "_groups";

    private String mId;
    private DatabaseReference mReference;

    //hacky client side grouping
    private DatabaseReference mGroupsReference;
    private DataSnapshot mGroups;

    final private Map<String, Listener> mListeners = new HashMap<>();
    final private Map<String, Ack> mCallbacks = new HashMap<>();

    public Messenger(String id, DatabaseReference reference) {
        this.mId = id;
        this.mReference = reference;
        this.mReference.orderByChild(KEY_TARGET).equalTo(mId).addChildEventListener(this);

        this.mGroupsReference = mReference.child(KEY_GROUPS);
        this.mGroupsReference.addValueEventListener(groupsListener);
    }

    public Emitter to(final String target){
        return new Emitter() {
            @Override
            public void emit(String event, String msg, Ack callback) {
                if(event == null) throw new IllegalArgumentException("event argument can't be null.");

                Message message = new Message(event, msg);
                message.setSource(mId);

                if(callback != null){
                    mCallbacks.put(message.getId(), callback);
                    message.setCallback(true);
                }

                if(mGroups == null || mGroups.hasChild(target)){
                    message.setTarget(target);
                    mReference.child(message.getId()).setValue(message);
                }else if(mGroups.exists()){
//                        DataSnapshot members = mGroups.child(target);
//                        if(members.exists()){
//                            for(Iterator<DataSnapshot> iterator = members.getChildren().iterator(); iterator.hasNext();){
//                                String subTarget = iterator.next().getKey();
//                                Message childMessage = message.getChildInstance();
//                                childMessage.setTarget(subTarget);
//                                mReference.child(childMessage.getId()).setValue(childMessage);
//                            }
//                        }
                    }
            }
        };
    }

    public void on(String event, Listener listener){
        if(listener == null){//remove current
            off(event);
        }else{
            mListeners.put(event, listener);
        }
    }

    public void off(String event){
        if(mListeners.containsKey(event)){
            mListeners.remove(event);
        }
    }

    public void join(String group){
        mGroupsReference.child(group).child(mId).setValue(0);
    }

    public void leave(String group){
        mGroupsReference.child(group).child(mId).removeValue();
    }

    ValueEventListener groupsListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    };


    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String s) {
        Message message = null;
        try{
            message = dataSnapshot.getValue(Message.class);

        }catch(DatabaseException e){
            e.printStackTrace();
        }

        if(message!= null){
            handleMessage(message);
        }

        //remove from database.
        dataSnapshot.getRef().removeValue();
    }

    private boolean handleMessage(final Message message) {
        String event = message.getType();
        if(mListeners.containsKey(event)){
            Ack callback = null;
            if(message.isCallback()){
                //route response to sending messenger
                callback = new Ack() {
                    @Override
                    public void call(String args) {
                        to(message.getSource()).emit(message.getId(), args);
                    }
                };
            }
            mListeners.get(event).call(message.getMessage(), callback);
            return true;

        //assume that none of the event listeners match the uuid of a message
        }else if(mCallbacks.containsKey(event)){
            mCallbacks.get(event).call(message.getMessage());
            mCallbacks.remove(event);
            return true;
        }
        return false;
    }

    @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String s) {

    }

    @Override
    public void onChildRemoved(DataSnapshot dataSnapshot) {

    }

    @Override
    public void onChildMoved(DataSnapshot dataSnapshot, String s) {

    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        databaseError.toException().printStackTrace();
    }

    public void disconnect(){
        mReference.removeEventListener(this);
    }

    public abstract class Emitter{
        public void emit(String event, String msg){
            emit(event, msg, null);
        }

        abstract public void emit(String event, String msg, Ack callback);
    }

    public interface Listener{
        void call(String args, Ack callback);
    }

    public interface Ack{
        void call(String args);
    }
}
