/*
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied.  See the License for the
  specific language governing permissions and limitations
  under the License.
 */

#import "CMISSession.h"
#import "CMISConstants.h"
#import "CMISObjectConverter.h"
#import "CMISStandardAuthenticationProvider.h"
#import "CMISBindingFactory.h"
#import "CMISObjectList.h"
#import "CMISQueryResult.h"
#import "CMISErrors.h"
#import "CMISOperationContext.h"
#import "CMISRequest.h"
#import "CMISPagedResult.h"
#import "CMISTypeDefinition.h"
#import "CMISDefaultNetworkProvider.h"
#import "CMISLog.h"

@interface CMISSession ()
@property (nonatomic, strong, readwrite) CMISObjectConverter *objectConverter;
@property (nonatomic, assign, readwrite, getter = isAuthenticated) BOOL authenticated;
@property (nonatomic, strong, readwrite) id<CMISBinding> binding;
@property (nonatomic, strong, readwrite) CMISRepositoryInfo *repositoryInfo;
@property (nonatomic, strong, readwrite) NSMutableDictionary *typeCache;
// Returns a CMISSession using the given session parameters.
- (id)initWithSessionParameters:(CMISSessionParameters *)sessionParameters;

// Authenticates using the CMISSessionParameters and returns if the authentication was successful
- (CMISRequest*)authenticateWithCompletionBlock:(void (^)(CMISSession *session, NSError * error))completionBlock;
@end

@interface CMISSession (PrivateMethods)
- (BOOL)authenticateAndReturnError:(NSError **)error;
@end

@implementation CMISSession

#pragma mark -
#pragma mark Setup

+ (CMISRequest*)arrayOfRepositories:(CMISSessionParameters *)sessionParameters completionBlock:(void (^)(NSArray *repositories, NSError *error))completionBlock
{
    CMISSession *session = [[CMISSession alloc] initWithSessionParameters:sessionParameters];
    
    // TODO: validate session parameters?
    
    // return list of repositories
    return [session.binding.repositoryService retrieveRepositoriesWithCompletionBlock:completionBlock];
}

+ (CMISRequest*)connectWithSessionParameters:(CMISSessionParameters *)sessionParameters
                     completionBlock:(void (^)(CMISSession *session, NSError * error))completionBlock
{
    CMISSession *session = [[CMISSession alloc] initWithSessionParameters:sessionParameters];
    if (session) {
        return [session authenticateWithCompletionBlock:completionBlock];
    } else {
        completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument
                                             detailedDescription:@"Not enough session parameters to connect"]);
        return nil;
    }
}

#pragma internal authentication methods

- (id)initWithSessionParameters:(CMISSessionParameters *)sessionParameters
{
    self = [super init];
    if (self) {
        self.sessionParameters = sessionParameters;
        self.authenticated = NO;
    
        // setup authentication provider if not present
        if (self.sessionParameters.authenticationProvider == nil) {
            NSString *username = self.sessionParameters.username;
            NSString *password = self.sessionParameters.password;
            if (username == nil || password == nil) {
                CMISLogError(@"No username or password provided for standard authentication provider");
                return nil;
            }
            
            self.sessionParameters.authenticationProvider = [[CMISStandardAuthenticationProvider alloc] initWithUsername:username
                                                                                                                password:password];
        }

        if (self.sessionParameters.networkProvider == nil) {
            self.sessionParameters.networkProvider = [[CMISDefaultNetworkProvider alloc] init];
        }
        
        // create the binding the session will use
        CMISBindingFactory *bindingFactory = [[CMISBindingFactory alloc] init];
        self.binding = [bindingFactory bindingWithParameters:sessionParameters];

        id objectConverterClassValue = [self.sessionParameters objectForKey:kCMISSessionParameterObjectConverterClassName];
        if (objectConverterClassValue != nil && [objectConverterClassValue isKindOfClass:[NSString class]]) {
            NSString *objectConverterClassName = (NSString *)objectConverterClassValue;
            CMISLogDebug(@"Using a custom object converter class: %@", objectConverterClassName);
            self.objectConverter = [[NSClassFromString(objectConverterClassName) alloc] initWithSession:self];
        } else { //default
            self.objectConverter = [[CMISObjectConverter alloc] initWithSession:self];
        }
        
        self.typeCache = [[NSMutableDictionary alloc] init]; //TODO this typeCache should be replaced by a binding specific type definition cache
    
        // TODO: setup locale
        // TODO: setup default session parameters
        // TODO: setup caches
    }
    
    return self;
}

- (CMISRequest*)authenticateWithCompletionBlock:(void (^)(CMISSession *session, NSError * error))completionBlock
{
    // TODO: validate session parameters, extract the checks below?
    
    // check repository id is present
    if (self.sessionParameters.repositoryId == nil) {
        NSError *error = [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument
                                         detailedDescription:@"Must provide repository id"];
        CMISLogError(@"Error: %@", error.description);
        completionBlock(nil, error);
        return nil;
    }
    
    if (self.sessionParameters.authenticationProvider == nil) {
        NSError *error = [CMISErrors createCMISErrorWithCode:kCMISErrorCodeUnauthorized detailedDescription:@"Must provide authentication provider"];
        CMISLogError(@"Error: %@", error.description);
        completionBlock(nil, error);
        return nil;
    }
    
    // TODO: use authentication provider to make sure we have enough credentials, it may need to make another call to get a ticket or do handshake i.e. NTLM.
    
    // get repository info
    return [self.binding.repositoryService retrieveRepositoryInfoForId:self.sessionParameters.repositoryId completionBlock:^(CMISRepositoryInfo *repositoryInfo, NSError *error) {
        self.repositoryInfo = repositoryInfo;
        if (self.repositoryInfo == nil) {
            if (error) {
                CMISLogError(@"Error because repositoryInfo is nil: %@", error.description);
                completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeInvalidArgument]);
            } else {
                completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument
                                                     detailedDescription:@"Could not fetch repository information"]);
            }
        } else {
            // no errors have occurred so set authenticated flag and return success flag
            self.authenticated = YES;
            completionBlock(self, nil);
        }
    }];
}


#pragma mark CMIS operations

- (CMISRequest*)retrieveRootFolderWithCompletionBlock:(void (^)(CMISFolder *folder, NSError *error))completionBlock
{
    return [self retrieveFolderWithOperationContext:[CMISOperationContext defaultOperationContext] completionBlock:completionBlock];
}

- (CMISRequest*)retrieveFolderWithOperationContext:(CMISOperationContext *)operationContext completionBlock:(void (^)(CMISFolder *folder, NSError *error))completionBlock
{
    NSString *rootFolderId = self.repositoryInfo.rootFolderId;
    return [self retrieveObject:rootFolderId operationContext:operationContext completionBlock:^(CMISObject *rootFolder, NSError *error) {
        if (rootFolder != nil && ![rootFolder isKindOfClass:[CMISFolder class]]) {
            completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeRuntime detailedDescription:@"Root folder object is not a folder!"]);
        } else {
            completionBlock((CMISFolder *)rootFolder, error);
        }
    }];
}

- (CMISRequest*)retrieveObject:(NSString *)objectId completionBlock:(void (^)(CMISObject *object, NSError *error))completionBlock
{
    return [self retrieveObject:objectId operationContext:[CMISOperationContext defaultOperationContext] completionBlock:completionBlock];
}

- (CMISRequest*)retrieveObject:(NSString *)objectId
      operationContext:(CMISOperationContext *)operationContext
       completionBlock:(void (^)(CMISObject *object, NSError *error))completionBlock
{
    if (objectId == nil) {
        completionBlock(nil, [CMISErrors createCMISErrorWithCode:kCMISErrorCodeInvalidArgument detailedDescription:@"Must provide object id"]);
        return nil;
    }

    // TODO: cache the object

    return [self.binding.objectService retrieveObject:objectId
                                               filter:operationContext.filterString
                                        relationships:operationContext.relationships
                                     includePolicyIds:operationContext.includePolicies
                                      renditionFilder:operationContext.renditionFilterString
                                           includeACL:operationContext.includeACLs
                              includeAllowableActions:operationContext.includeAllowableActions
                                      completionBlock:^(CMISObjectData *objectData, NSError *error) {
                                            if (error) {
                                                completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeObjectNotFound]);
                                            } else {
                                                CMISObject *object = nil;
                                                if (objectData) {
                                                    [self.objectConverter convertObject:objectData
                                                                        completionBlock:^(CMISObject *object, NSError *error) {
                                                                            completionBlock(object, error);
                                                    }];
                                                } else {
                                                    completionBlock(object, nil);
                                                }
                                            }
                                        }];
}

- (CMISRequest*)retrieveObjectByPath:(NSString *)path completionBlock:(void (^)(CMISObject *object, NSError *error))completionBlock
{
    return [self retrieveObjectByPath:path operationContext:[CMISOperationContext defaultOperationContext] completionBlock:completionBlock];
}

- (CMISRequest*)retrieveObjectByPath:(NSString *)path
            operationContext:(CMISOperationContext *)operationContext
             completionBlock:(void (^)(CMISObject *object, NSError *error))completionBlock
{
    return [self.binding.objectService retrieveObjectByPath:path
                                              filter:operationContext.filterString
                                       relationships:operationContext.relationships
                                    includePolicyIds:operationContext.includePolicies
                                     renditionFilder:operationContext.renditionFilterString
                                          includeACL:operationContext.includeACLs
                             includeAllowableActions:operationContext.includeAllowableActions
                                     completionBlock:^(CMISObjectData *objectData, NSError *error) {
                                        if (objectData != nil && error == nil) {
                                            [self.objectConverter convertObject:objectData
                                                                completionBlock:^(CMISObject *object, NSError *error) {
                                                                    completionBlock(object, error);
                                                                }];
                                         } else {
                                             if (error == nil) {
                                                 error = [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeObjectNotFound]; 
                                             }
                                             completionBlock(nil, error);
                                         }
                                     }];
}

- (CMISRequest*)retrieveTypeDefinition:(NSString *)typeId completionBlock:(void (^)(CMISTypeDefinition *typeDefinition, NSError *error))completionBlock
{
    CMISTypeDefinition *typeDefinition = [self.typeCache objectForKey:typeId];
    if (typeDefinition) {
        completionBlock(typeDefinition, nil);
        return nil;
    }
    
    return [self.binding.repositoryService retrieveTypeDefinition:typeId completionBlock:^(CMISTypeDefinition *typeDefinition, NSError *error) {
        if (typeDefinition) {
            [self.typeCache setObject:typeDefinition forKey:typeId];
        }
        completionBlock(typeDefinition, error);
    }];
}

- (CMISRequest*)query:(NSString *)statement searchAllVersions:(BOOL)searchAllVersion completionBlock:(void (^)(CMISPagedResult *pagedResult, NSError *error))completionBlock
{
    return [self query:statement searchAllVersions:searchAllVersion operationContext:[CMISOperationContext defaultOperationContext] completionBlock:completionBlock];
}

- (CMISRequest*)query:(NSString *)statement searchAllVersions:(BOOL)searchAllVersion
                                     operationContext:(CMISOperationContext *)operationContext
                                      completionBlock:(void (^)(CMISPagedResult *pagedResult, NSError *error))completionBlock
{
    CMISRequest *request = [[CMISRequest alloc] init];
    CMISFetchNextPageBlock fetchNextPageBlock = ^(int skipCount, int maxItems, CMISFetchNextPageBlockCompletionBlock pageBlockCompletionBlock){
        // Fetch results through discovery service
       CMISRequest *queryRequest = [self.binding.discoveryService query:statement
                                                  searchAllVersions:searchAllVersion
                                                  relationships:operationContext.relationships
                                                  renditionFilter:operationContext.renditionFilterString
                                                  includeAllowableActions:operationContext.includeAllowableActions
                                                  maxItems:[NSNumber numberWithInt:maxItems]
                                                  skipCount:[NSNumber numberWithInt:skipCount]
                                                  completionBlock:^(CMISObjectList *objectList, NSError *error) {
                                                      if (error) {
                                                          pageBlockCompletionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeRuntime]);
                                                      } else {
                                                          // Fill up return result
                                                          CMISFetchNextPageBlockResult *result = [[CMISFetchNextPageBlockResult alloc] init];
                                                          result.hasMoreItems = objectList.hasMoreItems;
                                                          result.numItems = objectList.numItems;
                                                          
                                                          NSMutableArray *resultArray = [[NSMutableArray alloc] init];
                                                          result.resultArray = resultArray;
                                                          for (CMISObjectData *objectData in objectList.objects) {
                                                              [resultArray addObject:[CMISQueryResult queryResultUsingCmisObjectData:objectData session:self]];
                                                          }
                                                          pageBlockCompletionBlock(result, nil);
                                                      }
                                                  }];
        
        // set the underlying request object on the object returned to the original caller
        request.httpRequest = queryRequest.httpRequest;
    };

    [CMISPagedResult pagedResultUsingFetchBlock:fetchNextPageBlock
                                limitToMaxItems:operationContext.maxItemsPerPage
                             startFromSkipCount:operationContext.skipCount
                                completionBlock:^(CMISPagedResult *result, NSError *error) {
                                    // Return nil and populate error in case something went wrong
                                    if (error) {
                                        completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeRuntime]);
                                    } else {
                                        completionBlock(result, nil);
                                    }
                                }];
    return request;
}

- (CMISRequest*)queryObjectsWithTypeDefinition:(CMISTypeDefinition *)typeDefinition
                           whereClause:(NSString *)whereClause
                     searchAllVersions:(BOOL)searchAllVersion
                      operationContext:(CMISOperationContext *)operationContext
                       completionBlock:(void (^)(CMISPagedResult *result, NSError *error))completionBlock
{
    // Creating the cmis query using the input params
    NSMutableString *statement = [[NSMutableString alloc] init];
    
    // Filter
    [statement appendFormat:@"SELECT %@", (operationContext.filterString != nil ? operationContext.filterString : @"*")];
    
    // Type
    [statement appendFormat:@" FROM %@", typeDefinition.queryName];
    
    // Where
    if (whereClause != nil) {
        [statement appendFormat:@" WHERE %@", whereClause];
    }
    
    // Order by
    if (operationContext.orderBy != nil) {
        [statement appendFormat:@" ORDER BY %@", operationContext.orderBy];
    }
    
    CMISRequest *request = [[CMISRequest alloc] init];
    
    // Fetch block for paged results
    CMISFetchNextPageBlock fetchNextPageBlock = ^(int skipCount, int maxItems, CMISFetchNextPageBlockCompletionBlock pageBlockCompletionBlock)
    {
        // Fetch results through discovery service
        CMISRequest *queryRequest = [self.binding.discoveryService query:statement
                                     searchAllVersions:searchAllVersion
                                         relationships:operationContext.relationships
                                       renditionFilter:operationContext.renditionFilterString
                               includeAllowableActions:operationContext.includeAllowableActions
                                              maxItems:[NSNumber numberWithInt:maxItems]
                                             skipCount:[NSNumber numberWithInt:skipCount]
                                       completionBlock:^(CMISObjectList *objectList, NSError *error) {
                                 if (error) {
                                     pageBlockCompletionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeRuntime]);
                                 } else {
                                     // Fill up return result
                                     CMISFetchNextPageBlockResult *result = [[CMISFetchNextPageBlockResult alloc] init];
                                     result.hasMoreItems = objectList.hasMoreItems;
                                     result.numItems = objectList.numItems;
                                     
                                     [self.objectConverter convertObjects:objectList.objects
                                                          completionBlock:^(NSArray *objects, NSError *error) {
                                                              result.resultArray = objects;
                                                              pageBlockCompletionBlock(result, error);
                                                          }];
                                 }
                             }];
        
        // set the underlying request object on the object returned to the original caller
        request.httpRequest = queryRequest.httpRequest;
    };
    
    [CMISPagedResult pagedResultUsingFetchBlock:fetchNextPageBlock
                                limitToMaxItems:operationContext.maxItemsPerPage
                             startFromSkipCount:operationContext.skipCount
                                completionBlock:^(CMISPagedResult *result, NSError *error) {
                                    // Return nil and populate error in case something went wrong
                                    if (error) {
                                        completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeRuntime]);
                                    } else {
                                        completionBlock(result, nil);
                                    }
                                }];
    return request;
}

- (CMISRequest*)queryObjectsWithTypeid:(NSString *)typeId
                   whereClause:(NSString *)whereClause
             searchAllVersions:(BOOL)searchAllVersion
              operationContext:(CMISOperationContext *)operationContext
               completionBlock:(void (^)(CMISPagedResult *result, NSError *error))completionBlock
{
    return [self retrieveTypeDefinition:typeId
                 completionBlock:^(CMISTypeDefinition *typeDefinition, NSError *internalError) {
                     if (internalError != nil) {
                         NSError *error = [CMISErrors cmisError:internalError cmisErrorCode:kCMISErrorCodeRuntime];
                         completionBlock(nil, error);
                     } else {
                         [self queryObjectsWithTypeDefinition:typeDefinition
                                                  whereClause:whereClause
                                            searchAllVersions:searchAllVersion
                                             operationContext:operationContext
                                              completionBlock:completionBlock];
                     }
                 }];
}

- (CMISRequest*)createFolder:(NSDictionary *)properties
            inFolder:(NSString *)folderObjectId
     completionBlock:(void (^)(NSString *objectId, NSError *error))completionBlock
{
    CMISRequest *request = [[CMISRequest alloc] init];
    [self.objectConverter convertProperties:properties
                            forObjectTypeId:[properties objectForKey:kCMISPropertyObjectTypeId]
                            completionBlock:^(CMISProperties *convertedProperties, NSError *error) {
                               if (error) {
                                   completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeRuntime]);
                               } else {
                                  CMISRequest *createRequest = [self.binding.objectService createFolderInParentFolder:folderObjectId
                                                                               properties:convertedProperties
                                                                          completionBlock:^(NSString *objectId, NSError *error) {
                                                                              completionBlock(objectId, error);
                                                                          }];
                                   // set the underlying request object on the object returned to the original caller
                                   request.httpRequest = createRequest.httpRequest;
                               }
                           }];
    return request;
}

- (CMISRequest*)downloadContentOfCMISObject:(NSString *)objectId
                                     toFile:(NSString *)filePath
                            completionBlock:(void (^)(NSError *error))completionBlock
                              progressBlock:(void (^)(unsigned long long bytesDownloaded, unsigned long long bytesTotal))progressBlock
{
    return [self downloadContentOfCMISObject:objectId
                                      toFile:filePath
                                      offset:nil
                                      length:nil
                             completionBlock:completionBlock
                               progressBlock:progressBlock];
}

- (CMISRequest*)downloadContentOfCMISObject:(NSString *)objectId
                                     toFile:(NSString *)filePath
                                     offset:(NSDecimalNumber*)offset
                                     length:(NSDecimalNumber*)length
                            completionBlock:(void (^)(NSError *error))completionBlock
                              progressBlock:(void (^)(unsigned long long bytesDownloaded, unsigned long long bytesTotal))progressBlock
{
    return [self.binding.objectService downloadContentOfObject:objectId
                                                      streamId:nil
                                                        toFile:filePath
                                                        offset:nil
                                                        length:nil
                                               completionBlock:completionBlock
                                                 progressBlock:progressBlock];
}

- (CMISRequest*)downloadContentOfCMISObject:(NSString *)objectId
                             toOutputStream:(NSOutputStream *)outputStream
                            completionBlock:(void (^)(NSError *error))completionBlock
                              progressBlock:(void (^)(unsigned long long bytesDownloaded, unsigned long long bytesTotal))progressBlock
{
    return [self downloadContentOfCMISObject:objectId
                              toOutputStream:outputStream
                                      offset:nil
                                      length:nil
                             completionBlock:completionBlock
                               progressBlock:progressBlock];
}

- (CMISRequest*)downloadContentOfCMISObject:(NSString *)objectId
                             toOutputStream:(NSOutputStream *)outputStream
                                     offset:(NSDecimalNumber*)offset
                                     length:(NSDecimalNumber*)length
                            completionBlock:(void (^)(NSError *error))completionBlock
                              progressBlock:(void (^)(unsigned long long bytesDownloaded, unsigned long long bytesTotal))progressBlock
{
    return [self.binding.objectService downloadContentOfObject:objectId
                                                      streamId:nil
                                                toOutputStream:outputStream
                                                        offset:offset
                                                        length:length
                                               completionBlock:completionBlock
                                                 progressBlock:progressBlock];
}


- (CMISRequest*)createDocumentFromFilePath:(NSString *)filePath
                          mimeType:(NSString *)mimeType
                        properties:(NSDictionary *)properties inFolder:(NSString *)folderObjectId
                   completionBlock:(void (^)(NSString *objectId, NSError *error))completionBlock
                     progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock
{
    CMISRequest *request = [[CMISRequest alloc] init];
    [self.objectConverter convertProperties:properties
                            forObjectTypeId:[properties objectForKey:kCMISPropertyObjectTypeId]
                            completionBlock:^(CMISProperties *convertedProperties, NSError *error) {
        if (error) {
            CMISLogError(@"Could not convert properties: %@", error.description);
            if (completionBlock) {
                completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeRuntime]);
            }
        } else {
            CMISRequest *createRequest = [self.binding.objectService createDocumentFromFilePath:filePath
                                                                    mimeType:mimeType
                                                                  properties:convertedProperties
                                                                    inFolder:folderObjectId
                                                             completionBlock:completionBlock
                                                               progressBlock:progressBlock];
            // set the underlying request object on the object returned to the original caller
            request.httpRequest = createRequest.httpRequest;
        }
    }];
    return request;
}

- (CMISRequest*)createDocumentFromInputStream:(NSInputStream *)inputStream
                             mimeType:(NSString *)mimeType
                           properties:(NSDictionary *)properties
                             inFolder:(NSString *)folderObjectId
                        bytesExpected:(unsigned long long)bytesExpected
                      completionBlock:(void (^)(NSString *objectId, NSError *error))completionBlock
                        progressBlock:(void (^)(unsigned long long bytesUploaded, unsigned long long bytesTotal))progressBlock
{
    CMISRequest *request = [[CMISRequest alloc] init];
    [self.objectConverter convertProperties:properties
                            forObjectTypeId:[properties objectForKey:kCMISPropertyObjectTypeId]
                            completionBlock:^(CMISProperties *convertedProperties, NSError *error) {
        if (error) {
            CMISLogError(@"Could not convert properties: %@", error.description);
            if (completionBlock) {
                completionBlock(nil, [CMISErrors cmisError:error cmisErrorCode:kCMISErrorCodeRuntime]);
            }
        } else {
            CMISRequest *createRequest = [self.binding.objectService createDocumentFromInputStream:inputStream
                                                             mimeType:mimeType
                                                           properties:convertedProperties
                                                             inFolder:folderObjectId
                                                        bytesExpected:bytesExpected
                                                      completionBlock:completionBlock
                                                        progressBlock:progressBlock];
            // set the underlying request object on the object returned to the original caller
            request.httpRequest = createRequest.httpRequest;
        }
    }];
    return request;
}

@end
