/*
 *  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];
                     });

    // Override default style to add interline space
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle  alloc] init];
    paragraphStyle.lineSpacing = 8;
    [chatView setDefaultParagraphStyle:paragraphStyle];
}

- (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;

    NSString* message = msgIdx.data(Qt::DisplayRole).value<QString>().toNSString();
    NSString* author = msgIdx.data((int)Media::TextRecording::Role::AuthorDisplayname).value<QString>().toNSString();

    NSMutableAttributedString* attr = [[NSMutableAttributedString alloc] initWithString:
                                [NSString stringWithFormat:@"%@: %@\n",author, message]];

    // put in bold type author name
    [attr applyFontTraits:NSBoldFontMask range: NSMakeRange(0, [author length])];

    [[chatView textStorage] appendAttributedString:attr];

    // reapply paragraph style on all the text
    NSRange range = NSMakeRange(0,[chatView textStorage].length);
    [[self.chatView textStorage] addAttribute:NSParagraphStyleAttributeName
                                        value:chatView.defaultParagraphStyle
                                        range:range];

    [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
