//
//  MPFunction.m
//  MathPad
//
//  Created by Kim Wittenburg on 18.04.14.
//  Copyright (c) 2014 Kim Wittenburg. All rights reserved.
//

#import "MPFunction.h"
#import "MPExpression.h"
#import "MPRangePath.h"

#import "NSIndexPath+MPAdditions.h"

@implementation MPFunction

#pragma mark Creation Methods
- (instancetype)init
{
    self = [super init];
    if (self) {
    }
    return self;
}

#pragma mark Working With the Expression Tree
- (MPExpression *)rootExpression
{
    return [self.parent rootExpression];
}

- (NSIndexPath *)indexPath
{
    NSUInteger selfIndex = [self.parent indexOfElement:self];
    return [[self.parent indexPath] indexPathByAddingIndex:selfIndex];
}

- (NSUInteger)numberOfChildren
{
    return 0;
}

- (MPExpression *)childAtIndex:(NSUInteger)index
{
    return nil;
}

- (void)setChild:(MPExpression *)child
         atIndex:(NSUInteger)index
{
    [self didChangeChildAtIndex:index];
}

- (NSArray *)children
{
    NSUInteger childCount = [self numberOfChildren];
    NSMutableArray *children = [[NSMutableArray alloc] initWithCapacity:childCount];
    for (NSInteger i = 0; i < childCount; i++) {
        [children addObject:[self childAtIndex:i]];
    }
    return [children copy];
}

- (NSUInteger)indexOfChild:(MPExpression *)child
{
    NSUInteger index = 0;
    for (; index < [self numberOfChildren]; index++) {
        if ([self childAtIndex:index] == child) {
            return index;
        }
    }
    return NSNotFound;
}

- (id)elementAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.length == 0) {
        return self;
    }
    MPExpression *child = [self childAtIndex:[indexPath indexAtPosition:0]];
    return [child elementAtIndexPath:[indexPath indexPathByRemovingFirstIndex]];
}

#pragma mark Evaluating Functions
- (NSDecimalNumber *)evaluate:(MPParseError *__autoreleasing *)error
{
    return [NSDecimalNumber zero];
}

#pragma mark Notifications
- (void)didChangeElementsInRangePath:(MPRangePath *)rangePath
                   replacementLength:(NSUInteger)replacementLength
{
    NSUInteger selfIndex = [self.parent indexOfElement:self];
    MPRangePath *newPath = MPMakeRangePath([rangePath.location indexPathByPreceedingIndex:selfIndex], rangePath.length);
    [self.parent didChangeElementsInRangePath:newPath
                            replacementLength:replacementLength];
}

- (void)didChangeChild:(MPExpression *)child
{
    [self didChangeChildAtIndex:[self indexOfChild:child]];
}

- (void)didChangeChildAtIndex:(NSUInteger)index
{
    MPRangePath *path = [[MPRangePath alloc] initWithRange:NSMakeRange(index, 1)];
    [self didChangeElementsInRangePath:path
                     replacementLength:1];
}

#pragma mark Working With Functions
/*
- (BOOL)isEqual:(id)object
{
    if (self == object) {
        return YES;
    }
    if (object == nil) {
        return NO;
    }
    if (![object isKindOfClass:[MPFunction class]]) {
        return NO;
    }
    return [self isEqualToFunction:(MPFunction *)object];
}

- (BOOL)isEqualToFunction:(MPFunction *)aFunction
{
    return [aFunction isMemberOfClass:[MPFunction class]] && [self isMemberOfClass:[MPFunction class]];
}*/

- (NSString *)description
{
    return @"[]";
}

- (NSUInteger)hash
{
    return 0;
}

#pragma mark - NSCopying
- (id)copyWithZone:(NSZone *)zone
{
    return [[MPFunction allocWithZone:zone] init];
}

#pragma mark - NSCoding
- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    if (self) {
        NSArray *children = [aDecoder decodeObject];
        NSInteger index = 0;
        for (MPExpression *child in children) {
            [self setChild:child atIndex:index];
            ++index;
        }
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.children];
}

#pragma mark - MPExpressionElement
- (BOOL)isString
{
    return NO;
}

- (BOOL)isFunction
{
    return YES;
}

- (NSUInteger)length
{
    return 1;
}

@end
