//
//  KMBSLogPopUp.m
//  BathyScaphe
//
//  Created by 堀 昌樹 on 12/04/24.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#import "KMBSLogPopUp.h"

#import "KMDocument.h"
#import "KMBSLogViewController.h"

#import "AppDefaults.h"
#import "CMRAttributedMessageComposer.h"
#import "CMRMessageAttributesTemplate.h"
#import "CMRThreadLinkProcessor.h"
#import "DatabaseManager.h"
#import "CMXPopUpWindowManager.h"
#import "CMRHostHandler.h"
#import <SGAppKit/NSTextView-SGExtensions.h>

@implementation KMBSLogPopUp
@synthesize owner = _owner;
@synthesize doc = _doc;
@synthesize documentView = _documentView;

// レスアンカーポップアップ用
- (NSAttributedString *)contentsForIndexes:(NSIndexSet *)indexes
{
if (kSpamFilterInvisibleAbonedBehavior == [CMRPref spamFilterBehavior]) {
	return [self contentsForIndexes:indexes
					  composingMask:CMRInvisibleAbonedMask
							compose:NO
					 attributesMask:CMRLocalAbonedMask];
} else {
	return [self contentsForIndexes:indexes
					  composingMask:CMRInvisibleAbonedMask
							compose:NO
					 attributesMask:(CMRLocalAbonedMask|CMRSpamMask)];
}
}

// 属性ポップアップ用
- (NSAttributedString *)contentsForIndexes:(NSIndexSet *)indexes
                             composingMask:(UInt32)composingMask
                                   compose:(BOOL)doCompose
                            attributesMask:(UInt32)attributesMask
{
	NSUInteger				size = [indexes lastIndex]+1;
	NSMutableAttributedString		*textBuffer_;
	CMRAttributedMessageComposer	*composer_;
	
	if (!indexes || [indexes count] == 0) {
        return nil;
    }
	if (self.owner.numberOfMessage < size) {
        return nil;
    }
	NSUInteger index = NSNotFound;
	NSRange inRange = NSMakeRange(0, size);
	composer_ = [[[CMRAttributedMessageComposer alloc] init] autorelease];
	textBuffer_ = [[NSMutableAttributedString alloc] init];
	[composer_ setAttributesMask:attributesMask];
	[composer_ setComposingMask:composingMask compose:doCompose];
	[composer_ setContentsStorage:textBuffer_];
	
	while ([indexes getIndexes:&index maxCount:1 inIndexRange:&inRange] > 0) {
		CMRThreadMessage *message = [self.doc messageAtIndex:index];
		[composer_ composeThreadMessage:message];
	}
	
	return [textBuffer_ autorelease];
}

// 逆参照ポップアップ用
- (NSAttributedString *)contentsForTargetIndex:(NSUInteger)messageIndex
								 composingMask:(UInt32)composingMask
									   compose:(BOOL)doCompose
								attributesMask:(UInt32)attributesMask
{
	NSUInteger	limit = [self.doc numberOfReadedMessages];
	NSUInteger	i;
	NSMutableAttributedString		*textBuffer_;
	CMRAttributedMessageComposer	*composer_;
	
	if (limit == 0) return nil;
	
	composer_ = [[[CMRAttributedMessageComposer alloc] init] autorelease];
	textBuffer_ = [[NSMutableAttributedString alloc] init];
	[composer_ setAttributesMask:attributesMask];
	[composer_ setComposingMask:composingMask compose:doCompose];
	[composer_ setComposingTargetIndex:messageIndex];
	[composer_ setContentsStorage:textBuffer_];
	
	for (i = 0; i < limit; i++) {
		CMRThreadMessage *message = [self.doc messageAtIndex:i];
		[composer_ composeThreadMessage:message];
	}
	
	return [textBuffer_ autorelease];
}

- (NSAttributedString *)attributedStringWithLinkContext:(id)aLink
{
	static NSMutableAttributedString *kBuffer = nil;
	
	NSString		*address_;
	NSString		*logPath_ = nil;
	NSString		*boardName_ = nil;	// added in PrincessBride and later.
	
	if (!aLink) {
        return nil;
    }
	if (!kBuffer) {
		kBuffer = [[NSMutableAttributedString alloc] init];
    }
	[kBuffer deleteCharactersInRange:[kBuffer range]];
	
	address_ = [[aLink stringValue] stringByDeletingURLScheme:@"mailto"];
	if (address_) {
		NSDictionary *attributes_;
		
		attributes_ = [[CMRMessageAttributesTemplate sharedTemplate] attributesForText];
		[[kBuffer mutableString] appendString:address_];
		[kBuffer setAttributes:attributes_ range:[kBuffer range]]; 
	} else if ([CMRThreadLinkProcessor parseThreadLink:aLink boardName:&boardName_ boardURL:NULL filepath:&logPath_]) {
		NSDictionary			*dict_;
		NSAttributedString		*template_;
		NSString				*title_;
		
		dict_ = [[[NSDictionary alloc] initWithContentsOfFile:logPath_] autorelease];
		if (!dict_) {
			// データベース上にあるか
			NSString *threadID = [[logPath_ stringByDeletingPathExtension] lastPathComponent];
			NSString *threadTitle = [[DatabaseManager defaultManager] threadTitleFromBoardName:boardName_ threadIdentifier:threadID];
			if (threadTitle) {
				title_ = [NSString stringWithFormat:@"%@ %C %@", threadTitle, 0x2014, boardName_];
			} else {
				title_ = boardName_;
			}
			//
			//			template_ = [[[NSAttributedString alloc] initWithString:title_] autorelease];
			//			if (!template_) {
			//                goto ErrInvalidLink;
			//            }
			//			[kBuffer setAttributedString:template_];
		} else {
			//            CMRThreadAttributes *attr_ = [[[CMRThreadAttributes alloc] initWithDictionary:dict_] autorelease];
			title_ = [NSString stringWithFormat:@"%@ %C %@", [dict_ objectForKey:CMRThreadTitleKey], 0x2014, boardName_];
        }
        template_ = [[[NSAttributedString alloc] initWithString:title_] autorelease];
        if (!template_) {
            goto ErrInvalidLink;
        }
        [kBuffer setAttributedString:template_];
	} else if ([CMRThreadLinkProcessor parseBoardLink:aLink boardName:&boardName_ boardURL:NULL]) {
		[kBuffer setAttributedString:[[[NSAttributedString alloc] initWithString:boardName_] autorelease]];
	} else {
		NSIndexSet	*indexes;
		NSAttributedString *message_;
		
		if (![self.owner isMessageLink:aLink messageIndexes:&indexes]) {
            goto ErrInvalidLink;
        }
		message_ = [self contentsForIndexes:indexes];
		if (message_) {
            [kBuffer appendAttributedString:message_];
        }
	}
	
	return kBuffer;
	
ErrInvalidLink:
	return nil;
}

- (BOOL) tryShowPopUpWindowWithLink : (id     ) aLink
                       locationHint : (NSPoint) loc
{
	NSPoint					location_ = loc;
	NSAttributedString		*context_;
	
	context_ = [self attributedStringWithLinkContext : aLink];
	if (nil == context_ || 0 == [context_ length])
		return NO;
	
	
	[CMRPopUpMgr showPopUpWindowWithContext : context_
								  forObject : aLink
									  owner : self.documentView.delegate
							   locationHint : location_];
	
	return YES;
}
- (BOOL) tryShowPopUpWindowSubstringWithRange : (NSRange		) subrange
								inTextStorage : (NSTextStorage *) storage
								 locationHint : (NSPoint		) loc
{
	NSString			*linkstr_;
	
	if (0 == subrange.length) return NO;
	if (nil == storage) return NO;
	if (NSMaxRange(subrange) >= [storage length]) return NO;
	
	linkstr_ = [storage string];
	linkstr_ = [linkstr_ substringWithRange : subrange];
	linkstr_ = CMRLocalResLinkWithString(linkstr_);
	
	return [self tryShowPopUpWindowWithLink : linkstr_
							   locationHint : loc];
}
- (BOOL)tryShowPopUpReverseAnchor:(NSUInteger)targetIndex locationHint:(NSPoint)location_
{
	NSAttributedString *contents_;
	contents_ = [self contentsForTargetIndex:targetIndex
							   composingMask:CMRInvisibleAbonedMask
									 compose:NO
							  attributesMask:(CMRLocalAbonedMask|CMRSpamMask)];
	if (!contents_ || [contents_ length] == 0) {
		// #warning 64BIT: Check formatting arguments
		// 2010-03-28 tsawada2 修正済
		NSString *notFoundString = [NSString stringWithFormat:[self localizedString: @"GyakuSansyou Not Found"], (unsigned long)(targetIndex+1)];
		contents_ = [[[NSAttributedString alloc] initWithString:notFoundString] autorelease];
	}
	
	[CMRPopUpMgr showPopUpWindowWithContext:contents_
								  forObject:self.doc.datIdentifier
									  owner:self.documentView.delegate
							   locationHint:location_];
	return YES;
}

- (BOOL)tryShowPopUpIDForEevent:(NSEvent *)theEvent
{
	NSPoint mouseLoc_ = (NSPeriodic == [theEvent type])
	? [[self.documentView window] convertScreenToBase:[theEvent locationInWindow]]
	: [theEvent locationInWindow];
	mouseLoc_ = [self.documentView convertPoint:mouseLoc_ fromView:nil];
	
	id value = [self.documentView attribute:BSMessageIDAttributeName atPoint:mouseLoc_ effectiveRange:NULL];
	if(!value) return NO;
	
	[self extractMessagesWithIDString:(NSString *)value popUpLocation:[theEvent locationInWindow]];
	return YES;
}

- (BOOL)tryShowPopUpMatchAttributes:(NSUInteger)messageAtributesMask locationHint:(NSPoint)location_
{
	NSRange				indexRange_;
	NSAttributedString	*contents_;
	NSUInteger			attributeMask_ = CMRAnyAttributesMask;
	
	// ブックマーク、ＡＡ以外の属性は無視する
	attributeMask_ &= ~CMRBookmarkMask;
	attributeMask_ &= ~CMRAsciiArtMask;
	
	indexRange_ = NSMakeRange(0, self.owner.numberOfMessage);
	if (0 == indexRange_.length)
		return NO;
	
	contents_ = [self contentsForIndexes:[NSIndexSet indexSetWithIndexesInRange:indexRange_]
						   composingMask:messageAtributesMask
								 compose:YES
						  attributesMask:attributeMask_];
	
	if (!contents_ || ![contents_ length]) {
		NSBeep();
		return NO;
	}
	[CMRPopUpMgr showPopUpWindowWithContext:contents_
								  forObject:self.doc.datIdentifier
									  owner:self.documentView.delegate
							   locationHint:location_];
	return YES;
}

- (void)closePopUpWindowForObject:(id)obj
{
	[CMRPopUpMgr performClosePopUpWindowForObject:obj];
}


#pragma mark ID Popup Support
- (void)extractMessagesWithIDString:(NSString *) IDString
					  popUpLocation:(NSPoint) location
{
	NSMutableAttributedString		*textBuffer_;
	CMRAttributedMessageComposer	*composer_;
	//	CMXPopUpWindowController		*popUp_;
	NSUInteger						nFound = 0;
	//	UInt32							attributesMask_ = CMRAnyAttributesMask;
	
	if (!IDString || [IDString length] == 0) return;
	
	composer_ = [[CMRAttributedMessageComposer alloc] init];
	textBuffer_ = [[NSMutableAttributedString alloc] init];
	/*	
	 attributesMask_ &= ~CMRAsciiArtMask;
	 attributesMask_ &= ~CMRBookmarkMask;
	 
	 [composer_ setAttributesMask : attributesMask_];*/
	// 「迷惑レス」で「表示しない」の場合は CMRAttributedMessageComposer 側が判断して生成しないのでこれで良い
	[composer_ setComposingMask: (CMRLocalAbonedMask|CMRInvisibleAbonedMask) compose : NO];	
	[composer_ setContentsStorage:textBuffer_];
	
	for(CMRThreadMessage *message in [self.doc messages]) {
		NSString *IDValue = [message valueForKey: @"IDString"];
		if (!IDValue || [IDValue length] == 0) continue;
		
		if ([IDValue isEqualToString: IDString]) {
			nFound++;
			[composer_ composeThreadMessage:message];
		}
	}
	
	if (0 == nFound) {
		// #warning 64BIT: Check formatting arguments
		// 2010-03-28 tsawada2 検証済
		NSString *notFoundString = [NSString stringWithFormat: [self localizedString: @"Such ID Not Found"], IDString];
		NSAttributedString *notFoundAttrStr = [[NSAttributedString alloc] initWithString:notFoundString];
		[textBuffer_ appendAttributedString:notFoundAttrStr];
		[notFoundAttrStr release];
	}
	
	//	popUp_ = 
	[CMRPopUpMgr showPopUpWindowWithContext:textBuffer_
								  forObject:self.doc.datIdentifier
									  owner:self.documentView.delegate
							   locationHint:location];
	
	[composer_ release];
	[textBuffer_ release];
	composer_ = nil;
	textBuffer_ = nil;
}


@end
