/*
 *  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(sourceStart, 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
