//
// Document.j
// Editor
//
// Created by Francisco Tolmasky on Date.
// Copyright 2005 - 2008, 280 North, Inc. All rights reserved.
//

import <Foundation/CPValue.j>
import <Foundation/CPURLConnection.j>

import <AppKit/CPDocument.j>

import <SlideKit/SKPresentation.j>

import "EditorController.j"
import "SavePanel.j"
import "AuthorizedConnection.j"
import "ExportTask.j"


var DocumentPresentationKey = "DocumentPresentationKey",
    DocumentUndoManagerKey  = "DocumentUndoManagerKey";

DocumentType            = @"280 Slides Presentation File";
DocumentExportType      = @"280 Slides Presentation Export File";

window.controlColor = [CPColor whiteColor];

var SharedWindowController  = nil;

@implementation Document : CPDocument
{
    CPString                _documentName;
    
    SKPresentation          _presentation;
    EditorController        _windowController;
    
    CPURLConnection         _openConnection;
    CPURLConnection         _saveConnection;
    
    DocumentDownloadSession _downloadSession;

    BOOL                    _isPublic;
}

- (id)initWithType:(CPString)aType error:(CPError)anError
{
    self = [super initWithType:aType error:anError];

    if (self)
    {
        _isPublic = NO;

        _presentation = [[SKPresentation alloc] initWithSlideMaster:[[ThemePanel sharedThemePanel] selectedSlideMaster]];

        [_presentation setUndoManager:[self undoManager]];
        
        // FIXME: !!!!
        if (!CPFeatureIsCompatible(CPJavaScriptShadowFeature))
        {
            if ([_presentation slideMasters][0]._FIXME_color)
                window.controlColor = [CPColor blackColor];
            else
                window.controlColor = [CPColor whiteColor];
        }
    }
            
    return self;
}

- (void)makeWindowControllers
{
    if (!SharedWindowController)
        SharedWindowController = [[EditorController alloc] initWithWindowCibName:nil];
    
    _windowController = SharedWindowController;
    
    [self addWindowController:_windowController];
}

- (CPString)displayName
{
    return _documentName ? _documentName : [super displayName];
}

- (BOOL)isPublic
{
    return _isPublic;
}

- (void)setPublic:(BOOL)flag
{
    _isPublic = !(flag == "0" || flag == "false" || !flag);
}

/*
- (void)windowControllerDidLoadNib:(CPWindowController)aWindowController
{
    [super windowControllerDidLoadNib:aWindowController];
}*/

- (SKPresentation)presentation
{
    return _presentation;
}

- (CPData)dataOfType:(CPString)aType error:({CPError})anError
{
    var dictionary = [CPDictionary dictionary],
        data = [CPData dataWithString:@""],
        archiver = [[CPKeyedArchiver alloc] initForWritingWithMutableData:data];

    [archiver encodeObject:_presentation forKey:DocumentPresentationKey];
    //[archiver encodeObject:[_presentation undoManager] forKey:DocumentUndoManagerKey];

    [archiver finishEncoding];
    
    if (aType == DocumentExportType)
        return data;
    
    [data setString:"documentName=" + encodeURIComponent(_documentName) + "&numSlides=" + [[_presentation slides] count] + "\n" + [data string]];
    
    return data;
}

- (void)readFromData:(CPData)aData ofType:(CPString)aType error:(CPError)anError
{
    var response = CPJSObjectCreateWithJSON([aData string]).response,
        archiveString = response.document;
        unarchiver = [[CPKeyedUnarchiver alloc] initForReadingWithData:[CPData dataWithString:archiveString]];

    _documentName = response.document_name;
    _presentation = [unarchiver decodeObjectForKey:DocumentPresentationKey];
    [_presentation setUndoManager:[self undoManager]];

    // Restore the undo manager if we've archived it.
    if ([unarchiver containsValueForKey:DocumentUndoManagerKey])
    {
        undoManager = [unarchiver decodeObjectForKey:DocumentUndoManagerKey];
        
        // Fix for: https://trac.280north.com/ticket/18
        // Avoid leaking the current undo manager.
        [[self undoManager] setGroupsByEvent:NO];
        
        [self setUndoManager:undoManager];
        [_presentation setUndoManager:undoManager];
    }
    
    [unarchiver finishDecoding];
    
    if(response.public)
        [self setPublic:response.public];

    //FIXME: !!!!
    if (!CPFeatureIsCompatible(CPJavaScriptShadowFeature))
    {
        if ([_presentation slideMasters][0]._FIXME_color)
            window.controlColor = [CPColor blackColor];
        else
            window.controlColor = [CPColor whiteColor];
    }
}

- (CPURL)proposedFileURL
{
    return BASE_URL + @"document.php?document_name=" + _documentName;
}

- (void)downloadToType:(CPString)aType sessionDelegate:(id)aSessionDelegate didDownloadSelector:(SEL)aDidDownloadSelector contextInfo:(id)aContextInfo 
{
    _downloadSession = DocumentDownloadSessionMake(aSessionDelegate, aDidDownloadSelector, aContextInfo);
    
    var exportTask = [[ExportTask alloc] initWithData:[self dataOfType:DocumentExportType error:nil] format:ExportTaskPowerPointXMLFormat];
    
    [exportTask setTitle:[self displayName]];
    [exportTask setDelegate:self];
    
    [exportTask export];
}

- (void)exportTask:(ExportTask)anExportTask didFailWithError:(CPString)anError
{
    objj_msgSend(_downloadSession.delegate, _downloadSession.didSaveSelector, self, NO, _downloadSession.contextInfo);
    
    _downloadSession = nil;
}

- (void)exportTask:(ExportTask)anExportTask didFinishWithResponse:(CPString)aResponse
{
    objj_msgSend(_downloadSession.delegate, _downloadSession.didSaveSelector, self, YES, _downloadSession.contextInfo);
    
    _downloadSession = nil;
}

- (void)saveDocument:(id)aSender
{
    if ([self fileURL] && [self fileURL].indexOf(BASE_URL + @"open_public.php") == 0)
        return [self saveDocumentAs:aSender];
    
    return [super saveDocument:aSender];
}

@end

function DocumentDownloadSessionMake(aDelegate, aDidSaveSelector, aContextInfo)
{
    return { delegate:aDelegate, didSaveSelector:aDidSaveSelector, contextInfo:aContextInfo };
}
