/*
 *  Copyright (C) 2015 Savoir-Faire Linux Inc.
 *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 *
 *  Additional permission under GNU GPL version 3 section 7:
 *
 *  If you modify this program, or any covered work, by linking or
 *  combining it with the OpenSSL project's OpenSSL library (or a
 *  modified version of that library), containing parts covered by the
 *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
 *  grants you additional permission to convey the resulting work.
 *  Corresponding Source for a non-source form of such a combination
 *  shall include the source code for the parts of OpenSSL used as well
 *  as that of the covered work.
 */

#import "ChatVC.h"

#import <QItemSelectionModel>
#import <qstring.h>

#import <media/media.h>
#import <media/text.h>
#import <media/textrecording.h>
#import <callmodel.h>

@interface MediaConnectionsHolder : NSObject

@property QMetaObject::Connection newMediaAdded;
@property QMetaObject::Connection newMessage;

@end

@implementation MediaConnectionsHolder

@end

@interface ChatVC ()

@property (unsafe_unretained) IBOutlet NSTextView *chatView;
@property (unsafe_unretained) IBOutlet NSTextField *messageField;
@property (unsafe_unretained) IBOutlet NSButton *sendButton;

@property MediaConnectionsHolder* mediaHolder;

@end

@implementation ChatVC
@synthesize messageField,chatView,sendButton, mediaHolder;

- (void)awakeFromNib
{
    NSLog(@"Init ChatVC");

    [self.view setWantsLayer:YES];
    [self.view setLayer:[CALayer layer]];
    [self.view.layer setBackgroundColor:[NSColor blackColor].CGColor];

    mediaHolder = [[MediaConnectionsHolder alloc] init];

    QObject::connect(CallModel::instance()->selectionModel(),
                     &QItemSelectionModel::currentChanged,
                     [=](const QModelIndex &current, const QModelIndex &previous) {
                         [self setupChat];
                     });
}

- (void) setupChat
{
    QObject::disconnect(mediaHolder.newMediaAdded);
    QObject::disconnect(mediaHolder.newMessage);

    QModelIndex callIdx = CallModel::instance()->selectionModel()->currentIndex();

    if (!callIdx.isValid())
        return;

    Call* call = CallModel::instance()->getCall(callIdx);

    /* check if text media is already present */
    if (call->hasMedia(Media::Media::Type::TEXT, Media::Media::Direction::IN)) {
        Media::Text *text = call->firstMedia<Media::Text>(Media::Media::Direction::IN);
        [self parseChatModel:text->recording()->instantMessagingModel()];
    } else if (call->hasMedia(Media::Media::Type::TEXT, Media::Media::Direction::OUT)) {
        Media::Text *text = call->firstMedia<Media::Text>(Media::Media::Direction::OUT);
        [self parseChatModel:text->recording()->instantMessagingModel()];
    } else {
        /* monitor media for messaging text messaging */
        mediaHolder.newMediaAdded = QObject::connect(call,
                                                     &Call::mediaAdded,
                                                     [self] (Media::Media* media) {
                                                         if (media->type() == Media::Media::Type::TEXT) {
                                                             QObject::disconnect(mediaHolder.newMediaAdded);
                                                             [self parseChatModel:((Media::Text*)media)->recording()->instantMessagingModel()];

                                                         }
                                                     });
    }
}

- (void) parseChatModel:(QAbstractItemModel *)model
{
    QObject::disconnect(mediaHolder.newMessage);
    [self.messageField setStringValue:@""];
    self.message = @"";
    [self.chatView.textStorage.mutableString setString:@""];

    /* put all the messages in the im model into the text view */
    for (int row = 0; row < model->rowCount(); ++row) {
        [self appendNewMessage:model->index(row, 0)];
    }

    /* append new messages */
    mediaHolder.newMessage = QObject::connect(model,
                                              &QAbstractItemModel::rowsInserted,
                                              [self, model] (const QModelIndex &parent, int first, int last) {
                                                        for (int row = first; row <= last; ++row) {
                                                            QModelIndex idx = model->index(row, 0, parent);
                                                            [self appendNewMessage:idx];
                                                        }
                                                    }
                                                    );
}

- (void) appendNewMessage:(const QModelIndex&) msgIdx
{
    if (!msgIdx.isValid())
        return;

    QVariant message = msgIdx.data();
    NSAttributedString* attr = [[NSAttributedString alloc] initWithString:
                                [NSString stringWithFormat:@"%@\n",message.value<QString>().toNSString()]];
    [[chatView textStorage] appendAttributedString:attr];
    [chatView scrollRangeToVisible:NSMakeRange([[chatView string] length], 0)];

}

- (IBAction)sendMessage:(id)sender {

    QModelIndex callIdx = CallModel::instance()->selectionModel()->currentIndex();
    Call* call = CallModel::instance()->getCall(callIdx);

    /* make sure there is text to send */
    NSString* text = self.message;
    if (text && text.length > 0) {
        call->addOutgoingMedia<Media::Text>()->send(QString::fromNSString(text));
        // Empty the text after sending it
        [self.messageField setStringValue:@""];
        self.message = @"";
    }
}

#pragma mark - NSTextFieldDelegate

- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector
{
    if (commandSelector == @selector(insertNewline:) && self.message.length > 0) {
        [self sendMessage:nil];
        return YES;
    }
    return NO;
}

@end
