/*
 *  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.
 */
#import "QNSTreeController.h"

#import <QDebug>

@interface Node : NSObject {
    NSMutableArray *children;
}
@end

@implementation Node
- (id) init
{
    if (self = [super init]) {
        children = [[NSMutableArray alloc] init];
    }
    return self;
}

- (void) addChild:(Node*) child AtIndex:(NSUInteger) idx
{
    [children insertObject:child atIndex:idx];
}

- (NSMutableArray*) children
{
    return children;
}

@end


@implementation QNSTreeController

- (id) initWithQModel:(QAbstractItemModel*) model
{
    self = [super init];
    self->privateQModel = model;

    NSMutableArray* nodes = [[NSMutableArray alloc] init];
    [self populate:nodes];

    [self connect];
    return [self initWithContent:nodes];
}

-(void) populate:(NSMutableArray*) nodes
{
    for (int i = 0 ; i < self->privateQModel->rowCount() ; ++i) {
        Node* n = [[Node alloc] init];
        //qDebug() << "POUPL TOP:"<< self->privateQModel->index(i, 0) ;
        [self populateChild:[n children] withParent:self->privateQModel->index(i, 0)];
        [nodes insertObject:n atIndex:i];
    }
}

- (void) populateChild:(NSMutableArray*) nodes withParent:(QModelIndex)qIdx
{
    if (!qIdx.isValid())
        return;
    for (int i = 0 ; i < self->privateQModel->rowCount(qIdx) ; ++i) {
        Node* n = [[Node alloc] init];
        [self populateChild:[n children] withParent:self->privateQModel->index(i, 0, qIdx)];
        [nodes insertObject:n atIndex:i];
    }
}

- (BOOL)isEditable
{
    return self->privateQModel->flags(self->privateQModel->index(0, 0)) | Qt::ItemIsEditable;
}

- (QModelIndex) indexPathtoQIdx:(NSIndexPath*) path
{
    NSUInteger myArray[[path length]];
    [path getIndexes:myArray];
    QModelIndex toReturn;

    for (int i = 0; i < path.length; ++i) {
        toReturn = self->privateQModel->index(myArray[i], 0, toReturn);
    }

    return toReturn;
}

- (QModelIndex) toQIdx:(NSTreeNode*) node
{
    return [self indexPathtoQIdx:node.indexPath];
}

- (NSIndexPath*) qIdxToNSIndexPath:(QModelIndex) qIdx
{
    QModelIndex tmp = qIdx.parent();
    NSMutableArray* allIndexes = [NSMutableArray array];
    while (tmp.isValid()) {
        [allIndexes insertObject:@(tmp.row()) atIndex:0];
        tmp = tmp.parent();
    }
    [allIndexes insertObject:@(qIdx.row()) atIndex:allIndexes.count];

    NSUInteger indexes[allIndexes.count];
    for (int i = 0 ; i < allIndexes.count ; ++i) {
        indexes[i] = [[allIndexes objectAtIndex:i] intValue];
    }
    return [[NSIndexPath alloc] initWithIndexes:indexes length:allIndexes.count];
}

- (void) insertNodeAtQIndex:(QModelIndex) qIdx
{
    NSIndexPath* path = [self qIdxToNSIndexPath:qIdx];
    //qDebug() << "insertNodeAt" << qIdx;
    //NSLog(@"insertNodeAt index: %@", path);
    if (path.length == 1 && [path indexAtPosition:0] <= [[self arrangedObjects] count])
        [self insertObject:[[Node alloc] init] atArrangedObjectIndexPath:path];
    else if (path.length > 1)
        [self insertObject:[[Node alloc] init] atArrangedObjectIndexPath:path];
}

- (void) removeNodeAtQIndex:(QModelIndex) qIdx
{
    NSIndexPath* path = [self qIdxToNSIndexPath:qIdx];
    if ([self.arrangedObjects descendantNodeAtIndexPath:path]) {
        //NSLog(@"removeNodeAt index: %@", path);
        [self removeObjectAtArrangedObjectIndexPath:path];
    }
}

- (void)connect
{
    QObject::connect(self->privateQModel,
                     &QAbstractItemModel::rowsInserted,
                     [=](const QModelIndex & parent, int first, int last) {
                         for( int row = first; row <= last; ++row) {
                             //qDebug() << "INSERTING:"<< self->privateQModel->index(row, 0, parent) ;
                             if(!self->privateQModel->index(row, 0, parent).isValid())
                                 continue;

                             [self insertNodeAtQIndex:self->privateQModel->index(row, 0, parent)];
                         }
                     });

    QObject::connect(self->privateQModel,
                     &QAbstractItemModel::rowsAboutToBeMoved,
                     [=](const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationRow) {
                        //NSLog(@"rows about to be moved, start: %d, end: %d, moved to: %d", sourceStart, sourceEnd, destinationRow);
                        /* first remove the row from old location
                          * then insert them at the new location on the "rowsMoved signal */
                         for( int row = sourceStart; row <= sourceEnd; row++) {
                             //TODO
                         }
                     });

    QObject::connect(self->privateQModel,
                     &QAbstractItemModel::rowsMoved,
                     [self](const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationRow) {
                         for( int row = sourceStart; row <= sourceEnd; row++) {
                             NSIndexPath* srcPath = [self qIdxToNSIndexPath:self->privateQModel->index(row, 0, sourceParent)];
                             NSIndexPath* destPath = [self qIdxToNSIndexPath:self->privateQModel->index(destinationRow, 0, destinationParent)];

                             [self moveNode:[self.arrangedObjects descendantNodeAtIndexPath:srcPath] toIndexPath:destPath];
                         }
                     });

    QObject::connect(self->privateQModel,
                     &QAbstractItemModel::rowsAboutToBeRemoved,
                     [self](const QModelIndex & parent, int first, int last) {
                         for( int row = first; row <= last; row++) {
                             //qDebug() << "REMOVING:"<< self->privateQModel->index(row, 0, parent) ;
                             if (!self->privateQModel->index(row, 0, parent).isValid())
                                 continue;

                             [self removeNodeAtQIndex:self->privateQModel->index(row, 0, parent)];
                         }
                     });

    QObject::connect(self->privateQModel,
                     &QAbstractItemModel::rowsRemoved,
                     [self](const QModelIndex& parent, int first, int last) {

                     });

    QObject::connect(self->privateQModel,
                     &QAbstractItemModel::layoutChanged,
                     [self]() {
                         //NSLog(@"layout changed");
                         [self rearrangeObjects];
                     });

    QObject::connect(self->privateQModel,
                     &QAbstractItemModel::dataChanged,
                     [self](const QModelIndex &topLeft, const QModelIndex &bottomRight) {
                         for(int row = topLeft.row() ; row <= bottomRight.row() ; ++row)
                         {
                             QModelIndex tmpIdx = self->privateQModel->index(row, 0);
                             if(tmpIdx.row() >= [self.arrangedObjects count]) {
                                 Node* n = [[Node alloc] init];
                                 if(tmpIdx.isValid())
                                     [self insertObject:n atArrangedObjectIndexPath:[[NSIndexPath alloc] initWithIndex:row]];
                             }
                         }
                         [self rearrangeObjects];
                     });
}

@end
