//---------------------------------------------------------------------------------------------
//
//  Mail.m (iOS5以降のみ対応)
//  X-BASIC'
//
//  Created by AIG-Soft(iMac) on 2012/12/17.
//  Copyright (c) 2012-15年 AIG-Soft. All rights reserved.
//
//---------------------------------------------------------------------------------------------

#import "Mail.h"
#import "click.h"
#import "libs.h"
#import "ZipArchive.h"
#import "FileControl2.h"
#import "UIActivityIndicatorView+show.h"

@implementation Mail

//---------------------------------------------------------------------------------------------

-(id)initWithViewController:(UIViewController *)viewController_
{
	self=[super init];
	if (self!=nil) {
		viewController=viewController_; // assign
	}
	return self;
}

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
	nslog(@"メイル処理終了:result=%d/error=%@",result,error);
	// どの様な状態から帰ってきたとしても、画面から消す
	switch (result)
	{
		case MFMailComposeResultCancelled:
			// キャンセルされた(下書き削除)
			nslog(@"MFMailComposeResultCancelled");
			break;
		case MFMailComposeResultSaved:
			// 下書きが保存された
			nslog(@"MFMailComposeResultSaved");
			break;
		case MFMailComposeResultSent:
			// 送信された
			nslog(@"MFMailComposeResultSent");
			break;
		case MFMailComposeResultFailed:
			// 送信失敗
			nslog(@"MFMailComposeResultFailed:error=%@",error);
			break;
		default:
			nslog(@"状態不明");
			break;
	}
	// 閉じる
	[controller dismissViewControllerAnimated:YES completion:^(){
		nslog(@"消去終了");
		// こちらのほうがSENDより後に発生する
		self.fMailDone=MAIL_STAT_WAIT_DISMISS; // KVO発生
	}];
	
	// 中間ファイルを消す
	if (_tmpzip!=nil) {
		nslog(@"削除tmpzip=%@",_tmpzip);
#if COMPILE_MODE==2	// 本番では中間ファイルを削除する
		fileDelete(_tmpzip);
#endif
	}
	
	// 終了したら自分で開放する
	nslog(@"終了したのでmailを解放");
	mail=nil;

	// 処理終了；実はこちらのほうが先に発生する
	self.fMailDone=MAIL_STAT_WAIT_SEND; // KVO発生
}

// e-mailで送信する
// subject    : 件名
// body		  : 本文
// attachment : 添付データのフルパス名群
// zipfname   : nilでないときは、attachFilesをzipファイルに圧縮する
// 宛先などはメイラー上で入力する
-(void)eMailSend:(NSString *)subject body:(NSString *)body attachment:(NSArray *)attachFiles zip:(NSString *)zipfname
{
	nslog(@"eMailSend");
	
	UIActivityIndicatorView *indicator=[UIActivityIndicatorView show:viewController.view style:UIActivityIndicatorViewStyleWhiteLarge fbackground:YES];
	
	// 今回はメイル用クラスを使う(UINavigationControllerの子クラス)
	 // 念のため
	mail=[[MFMailComposeViewController alloc]init];

	// 件名
	nslog(@"件名:%@",subject);
	[mail setSubject:subject];
	// 本文
	nslog(@"本文:%@",body);
	[mail setMessageBody:body isHTML:NO];
	
	self.tmpzip=nil;
	if (zipfname!=nil) {
		nslog(@"Zip圧縮添付");
		self.tmpzip=makeFullPathForTemporaryPath(zipfname); // 中間ファイルを作る(retainするのでself.〜にする)
		nslog2(@"tmpzip=%@",self.tmpzip);
		//
		int cnt=0;
		ZipArchive *zip = [[ZipArchive alloc] init];
		BOOL ret;
		[zip CreateZipFile2:self.tmpzip];
		for (NSString *path in attachFiles) {
			nslog2(@"zip圧縮中:%@",path);
			if (!isFileExist(path)) {
				nslog2(@"ファイルが存在しない:%@",path);
				continue; // 次へ
			}
#if 0
			// これではフルパス名分のフォルダ構造が入ってしまう＝iOS内での記録フォルダ構成が全て再現されてしまう
			ret = [zip addFileToZip:self.tmpzip newname:path];
#else
			// フォルダ構造を作らない
			ret = [zip addFileToZipWithFilenameOnly:self.tmpzip newname:path];
#endif
			if (!ret) break; // エラーが出たら打ち切り(手抜き)
			// 圧縮できたファイル数
			cnt++;
		}
		if ([zip CloseZipFile2]) {
			// 圧縮正常終了
			if (cnt>0) {
				NSData *attach=[[NSData alloc]initWithContentsOfFile:self.tmpzip];
				[mail addAttachmentData:attach mimeType:@"application/zip" fileName:zipfname];
			} else {
				nslog2(@"実際には圧縮されたファイルがないので添付しない");
			}
		} else {
			nslog2(@"zip圧縮エラー");
			// エラー処理
			// 現在は手抜きで処理なし
			// エラーがあったときは添付が付かないことで判定
		}
	} else {
		nslog2(@"個別添付");
		for (NSString *path in attachFiles) {
			if (!isFileExist(path)) {
				nslog2(@"ファイルが存在しない:%@",path);
				break;
			}
			NSString *filename=[path lastPathComponent]; // ファイル名のみ
			NSString *ext=[[path pathExtension]lowercaseString];
			// mimeTypeは http://www.iana.org/assignments/media-types/ 参照
			NSString *mimeType=@"application/octet-stream"; // その他の時は単なるデータとする(面倒だから)
			if ([ext caseInsensitiveCompare:@"pdf"]==NSOrderedSame) mimeType=@"application/pdf";
			else
			if ([ext caseInsensitiveCompare:@"jpg"]==NSOrderedSame) mimeType=@"image/jpeg";
			else
			if ([ext caseInsensitiveCompare:@"png"]==NSOrderedSame) mimeType=@"image/png";
			else
			if (  [ext caseInsensitiveCompare:@"txt"]==NSOrderedSame
			//	||[ext caseInsensitiveCompare:EXT_BASIC]==NSOrderedSame		// BASICソース	V2.8で削除
				) {
				mimeType=@"text/plain";
			}
			NSData *attach=[[NSData alloc]initWithContentsOfFile:path];
			[mail addAttachmentData:attach mimeType:mimeType fileName:filename];
		}
	}
	[indicator dismiss];
	
	// メイラーを開く
	// e-mailは実機 or Xcode 4.2でないと起動できない
	mail.mailComposeDelegate=self; // 普通のdelegeteではないので注意
	
	nslog(@"viewController=%@",viewController);
	nslog(@"isMainThread=%d/isMultiThreaded=%d",[NSThread isMainThread],[NSThread isMultiThreaded]);
	[viewController presentViewController:mail animated:YES completion:^(){
		nslog(@"表示完了");
		self.fMailDone=MAIL_STAT_WAIT_PRESENT; // KVO発生
	}];
	nslog(@"eMailSend end");
}

-(void)eMailSendInMainThreadSub:(NSArray *)arg
{
	printSelfs(@":%@",arg);
	@autoreleasepool {
		NSString 	*subject	=arg[0];
		NSString 	*body		=arg[1];
		NSArray 	*attachFiles=nil;
		if ([arg count]>=3) {
			attachFiles=arg[2];
		}
		NSString	*zipfname	=nil;
		if ([arg count]>=4) {
			zipfname=arg[3];
		}
		[self eMailSend:subject body:body attachment:attachFiles zip:zipfname];
	}
	printSelfs(@"(%@)",@"end");
}

-(void)eMailSendInMainThread:(NSString *)subject body:(NSString *)body attachment:(NSArray *)attachFiles zip:(NSString *)zipfname
{
	int checkBreakIniOS(void);

	nslog(@"eMailSendInMainThread");
	// メインスレッドで実行させるため、引数群をargに入れる
	NSArray *arg=[NSArray arrayWithObjects:
				  subject,
				  body,
				  // 以下2つはnilの場合もある
				  attachFiles,
				  zipfname,
				  nil];
#if 0	// modernでの書き方はこのようになるが、この場合attachFilesやzipfnameがnilの時落ちてしまうので直さない
	NSArray *arg=@[subject,
				   body,
				   // 以下2つはnilの場合もある
				   attachFiles,
				   zipfname];
#endif
	//
	self.fMailDone=MAIL_STAT_NOT_START;	// KVOを発生させないためself.にしない(念のため)
	// KVO設定
	[self addObserver:self forKeyPath:OBSERVE_FMAILDONE options:NSKeyValueObservingOptionNew context:NULL];
	//
	[self performSelectorOnMainThread:@selector(eMailSendInMainThreadSub:) withObject:arg waitUntilDone:YES];
	
	// メイラー表示待ち
	nslog(@"メイラー表示待ち");
	// ここは自動的に画面遷移するのでbreakチェックはしない
	while (self.fMailDone!=MAIL_STAT_WAIT_PRESENT);

	nslog(@"メイル送信終了待ち");
	self.fMailDone=MAIL_STAT_WAIT_SEND;
	
	// waitUntilDoneになっているが、メイル処理はビューが表示された時点で終了している(その後の処理は並行動作)ので、
	// BASICで使うには、別途メイルから完全に戻ってくるまで待つ必要がある。
	while (self.fMailDone!=MAIL_STAT_WAIT_SEND) {
		EnterRunLoop(0.0); // 念のため
		if (checkBreakIniOS()) break; // Breakが押された
	}
	nslog(@"メイル送信終了");
	
	// メイラー表示消し待ち；これが非常に重要
	// 先に開いていたものの消しが完了した後でないと、次の表示をしてはいけないから
	nslog(@"メイラー表示消し待ち");
	// ここは自動的に画面遷移するのでbreakチェックはしない
	while (self.fMailDone!=MAIL_STAT_WAIT_DISMISS);
	
	// key-value通知解除
	[self removeObserver:self forKeyPath:OBSERVE_FMAILDONE];
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
// KVOによる変更通知受信
{
	// OS経由で受信するだけ
	nslog(@"fMailDone=%@",object);
}

@end
