//******************************************************************************
//
// MIDITrail / MTFileEditViewCtrl
//
// ファイル編集ビュー制御クラス
//
// Copyright (C) 2018-2021 WADA Masashi. All Rights Reserved.
//
//******************************************************************************

#import "YNBaseLib.h"
#import "MTFileEditViewCtrl.h"


//******************************************************************************
// プライベートメソッド定義
//******************************************************************************
@interface MTFileEditViewCtrl ()

//テーブルセル作成：ファイル
- (UITableViewCell*)makeFileEditCell;

//テーブルセル作成：ロケーション
- (UITableViewCell*)makeLocationCellForIndexPath:(NSIndexPath*)indexPath;

//テーブルセル選択イベント：ロケーション
- (void)onSelectLocationCellForIndexPath:(NSIndexPath*)indexPath;

//ディレクトリ一覧生成
- (int)makeDirectoryList;

//ディレクトリ検索
- (int)searchDirectoriesForPath:(NSString*)pTargetDirPath directoryArray:(NSMutableArray*)pDirectoryArray;

//通知送信処理
- (int)postNotificationWithName:(NSString*)pName;

@end


@implementation MTFileEditViewCtrl

//******************************************************************************
// 生成
//******************************************************************************
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
	NSArray* pPathList = nil;
	
	self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
	
	m_pFileName = nil;
	m_pExtension = nil;
	m_pCurrentDirPath = nil;
	m_pSelectedDirPath = nil;
	m_pNewFileName = nil;
	m_pNotificationNameForEditFile = nil;
	m_pNotificationNameForCreateDir = nil;
	m_pDirPathList = nil;
	m_isCreatingDir = false;
	m_isDirListing = false;
	
	//Documentsディレクトリパスを取得
	pPathList = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
	m_pDocumentsDirPath = [pPathList objectAtIndex:0];
	[m_pDocumentsDirPath retain];
	
    return self;
}

//******************************************************************************
// ファイル編集通知名称設定
//******************************************************************************
- (void)setNotificationNameForEditFile:(NSString*)pNotificationName
{
	[m_pNotificationNameForEditFile release];
	m_pNotificationNameForEditFile = [pNotificationName retain];
}

//******************************************************************************
// ディレクトリ作成通知名称設定
//******************************************************************************
- (void)setNotificationNameForCreateDir:(NSString*)pNotificationName
{
	[m_pNotificationNameForCreateDir release];
	m_pNotificationNameForCreateDir = [pNotificationName retain];
}

//******************************************************************************
// 編集用ファイルパス設定（ただし編集対象がディレクトリの場合もある）
//******************************************************************************
- (void)setFilePathForEditing:(NSString*)pFilePath
{
	NSString* pFileName = nil;
	NSString* pDirPath = nil;
	BOOL isDir = NO;
	
	[m_pFileName release];
	[m_pExtension release];
	[m_pCurrentDirPath release];
	[m_pSelectedDirPath release];
	
	//ファイル名と拡張子の確認
	pFileName = [pFilePath lastPathComponent];
	if ([[NSFileManager defaultManager] fileExistsAtPath:pFilePath isDirectory:&isDir]) {
		if (isDir) {
			//ディレクトリの場合
			m_pFileName = [pFileName retain];
			m_pExtension = @"";
		}
		else {
			//ファイルの場合：ファイル名と拡張子を分割して保持する
			m_pFileName = [[pFileName stringByDeletingPathExtension] retain];
			m_pExtension = [[pFileName pathExtension] retain];
		}
	}
	
	//指定されたファイル（またはディレクトリ）の親ディレクトリのパス
	pDirPath = [pFilePath stringByDeletingLastPathComponent];
	[pDirPath retain];
	[pDirPath retain];
	m_pCurrentDirPath = pDirPath;
	m_pSelectedDirPath = pDirPath;
	
	//ディレクトリ作成フラグ初期化
	m_isCreatingDir = false;
	
	//タイトル
	self.title = @"Edit File";
	if (isDir) {
		self.title = @"Edit Folder";
	}
	
	return;
}

//******************************************************************************
// ディレクトリ作成用ディレクトリパス設定
//******************************************************************************
- (void)setDirPathForCreatingDir:(NSString*)pDirPath
{
	[m_pFileName release];
	[m_pExtension release];
	[m_pCurrentDirPath release];
	[m_pSelectedDirPath release];
	
	//ファイル名と拡張子
	m_pFileName = @"";
	m_pExtension = @"";
	
	//指定された親ディレクトリのパス
	[pDirPath retain];
	[pDirPath retain];
	m_pCurrentDirPath = pDirPath;
	m_pSelectedDirPath = pDirPath;
	
	//ディレクトリ作成フラグ初期化
	m_isCreatingDir = true;
	
	//タイトル
	self.title = @"New Folder";
	
	return;
}

//******************************************************************************
// ビュー登録完了
//******************************************************************************
- (void)viewDidLoad
{
	int result = 0;
	UIBarButtonItem* pSaveButton = nil;
	
	NSLog(@"MTFileEditViewCtrl viewDidLoad");
	
    [super viewDidLoad];
	
	//ナビゲーションバー右側にSaveボタンを配置
	pSaveButton = [[UIBarButtonItem alloc]
				   initWithBarButtonSystemItem:UIBarButtonSystemItemSave
				   target:self
				   action:@selector(onSaveButton:)];
	self.navigationItem.rightBarButtonItem = pSaveButton;
	
EXIT:;
	if (result != 0) YN_SHOW_ERR();
	return;
}

//******************************************************************************
// インターフェース自動回転確認
//******************************************************************************
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
	return YES;
}

//******************************************************************************
// インターフェース自動回転確認（iOS6以降）
//******************************************************************************
- (BOOL)shouldAutorotate
{
	//回転を許可する
	return YES;
}

//******************************************************************************
// インターフェース自動回転確認：回転方向（iOS6以降）
//******************************************************************************
- (NSUInteger)supportedInterfaceOrientations
{
	//全方向に対応する
	return UIInterfaceOrientationMaskAll;
}

//******************************************************************************
// ビュー表示
//******************************************************************************
- (void)viewWillAppear:(BOOL)animated
{
	int result = 0;
	
	//ディレクトリ一覧作成
	m_pDirPathList = nil;
	result = [self makeDirectoryList];
	if (result != 0) goto EXIT;
	
	//ディレクトリ一覧表示の初期状態はオフ
	m_isDirListing = false;
	
	[m_pTableView reloadData];
	
EXIT:;
	if (result != 0) YN_SHOW_ERR();
	return;
}

//******************************************************************************
// ビュー非表示
//******************************************************************************
- (void)viewWillDisappear:(BOOL)animated
{
	return;
}

//******************************************************************************
// セクション数
//******************************************************************************
-(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
{
	//セクション
	// 0. ファイル名
	// 1. ロケーション
    return 2;
} 

//******************************************************************************
// セクションヘッダ
//******************************************************************************
- (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section
{
	NSString* pSectionHeader = nil;
	
	switch(section) {
		case 0:
			//ファイル名
			pSectionHeader = @"Name";
			break;
		case 1:
			//ロケーション
			pSectionHeader = @"Location";
			break;
		default:
			break;
    }
	
    return pSectionHeader;
} 

//******************************************************************************
// セクションごとの項目数
//******************************************************************************
- (NSInteger)tableView:(UITableView *)tableView
 numberOfRowsInSection:(NSInteger)section
{
	NSInteger numOfRows = 0;
	
	//NSLog(@"section %d", section);
	
	switch (section) {
		case 0:
			//ファイル名
			numOfRows = 1;
			break;
		case 1:
			//ロケーション
			numOfRows = 1;
			if (m_isDirListing) {
				//ディレクトリ展開している場合
				numOfRows = [m_pDirPathList count];
			}
			break;
		default:
			break;
	}
	
	return numOfRows;
}

//******************************************************************************
// 項目表示内容
//******************************************************************************
- (UITableViewCell*)tableView:(UITableView*)tableView
		cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
	UITableViewCell* pCell = nil;
	
	switch (indexPath.section) {
		case 0:
			//ファイル名
			pCell = [self makeFileEditCell];
			break;
		case 1:
			//ロケーション
			pCell = [self makeLocationCellForIndexPath:(NSIndexPath*)indexPath];
			break;
		default:
			break;
	}
	
    return pCell;
}

//******************************************************************************
// 項目インデントレベル
//******************************************************************************
- (NSInteger)tableView:(UITableView *)tableView
	indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath;
{
	NSInteger indentationLevel = 0;
	NSString* pDirectoryPath = nil;
	
	switch (indexPath.section) {
		case 0:
			//ファイル名
			indentationLevel = 0;
			break;
		case 1:
			//ロケーション
			//  Documentsディレクトリからの相対的な階層数をインデントレベルとする
			//  インデントレベル0: Documentsディレクトリ
			//  インデントレベル1: Documentsディレクトリ直下に存在するファイル
			pDirectoryPath = [m_pDirPathList objectAtIndex:indexPath.row];
			indentationLevel = [[pDirectoryPath pathComponents] count] - [[m_pDocumentsDirPath pathComponents] count];
			break;
		default:
			break;
	}
	
    return indentationLevel;
}

//******************************************************************************
// テーブルセル作成：ファイル
//******************************************************************************
- (UITableViewCell*)makeFileEditCell
{
    static NSString* pCellIdentifier = @"MTFileEditViewCtrl_File";
	UITableViewCell* pCell = nil;
	UITextField* pTextField = nil;
	CGRect rectTextField;
	
	//再利用可能セル生成
	pCell = [m_pTableView dequeueReusableCellWithIdentifier:pCellIdentifier];
	if (pCell == nil) {
		pCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
									   reuseIdentifier:pCellIdentifier];
		//テキストフィールド追加
		rectTextField = CGRectMake(10, 8, m_pTableView.frame.size.width - (10 * 2), m_pTableView.rowHeight - (8 * 2));
		pTextField = [[UITextField alloc] initWithFrame:rectTextField];
		pTextField.borderStyle = UITextBorderStyleNone;
		pTextField.clearButtonMode = UITextFieldViewModeAlways;
		pTextField.delegate = self;
		pTextField.tag = 1;
		pTextField.borderStyle = UITextBorderStyleNone;
		//pTextField.borderStyle = UITextBorderStyleRoundedRect;
		[pCell.contentView addSubview:pTextField];
	}
	
	//テキストフィールドにファイル名を設定
	pTextField = (UITextField*)[pCell.contentView viewWithTag:1];
	pTextField.text = m_pFileName;
	pTextField.placeholder = m_pFileName;
	if (m_isCreatingDir) {
		pTextField.placeholder = @"New Folder";
	}
	
	//ラベルは空文字
	pCell.textLabel.text = @"";
	
	return pCell;
}

//******************************************************************************
// テーブルセル作成：ロケーション
//******************************************************************************
- (UITableViewCell*)makeLocationCellForIndexPath:(NSIndexPath*)indexPath
{
    static NSString* pCellIdentifier = @"MTFileEditViewCtrl_Dir";
	UITableViewCell* pCell = nil;
	NSString* pDirPath = nil;
	NSString* pDirName = nil;
	
	//再利用可能セル生成
	pCell = [m_pTableView dequeueReusableCellWithIdentifier:pCellIdentifier];
	if (pCell == nil) {
		pCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
									   reuseIdentifier:pCellIdentifier];
	}
	
	if (m_isDirListing) {
		//ディレクトリ一覧表示の場合
		pDirPath = [m_pDirPathList objectAtIndex:indexPath.row];
		pDirName = [pDirPath lastPathComponent];
		pCell.textLabel.text = pDirName;
        pCell.accessoryType = UITableViewCellAccessoryNone;
		if ([pDirPath isEqualToString:m_pSelectedDirPath]) {
			//選択中のディレクトリにチェックマーク設定
			pCell.accessoryType = UITableViewCellAccessoryCheckmark;
		}
	}
	else {
		//選択中ディレクトリ単独表示
		pDirName = [m_pSelectedDirPath lastPathComponent];;
		pCell.textLabel.text = pDirName;
		pCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; //階層マーク
	}
	
	return pCell;
}

//******************************************************************************
// テーブルセル作成：列の高さ
//******************************************************************************
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath
{
	CGFloat height = 0.0f;
	
	//デフォルトの高さを返す
	height = m_pTableView.rowHeight;
	
	return height;
}

//******************************************************************************
// テーブルセル選択イベント
//******************************************************************************
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
	//選択状態解除
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
	
	switch (indexPath.section) {
		case 0:
			//ファイル名
			//何もしない
			break;
		case 1:
			//ロケーション
			[self onSelectLocationCellForIndexPath:indexPath];
			break;
		default:
			break;
	}
	
	return;
}

//******************************************************************************
// テーブルセル選択イベント：ロケーション
//******************************************************************************
- (void)onSelectLocationCellForIndexPath:(NSIndexPath*)indexPath
{
	int result = 0;
	NSIndexSet* pSections = nil;
	NSRange range = NSMakeRange(1, 1);
	
	//ディレクトリ一覧表示でディレクトリを選択された場合
	if (m_isDirListing) {
		//選択されたディレクトリのパスを保管
		[m_pSelectedDirPath release];
		m_pSelectedDirPath = [m_pDirPathList objectAtIndex:indexPath.row];
		[m_pSelectedDirPath retain];
	}
	
	//ディレクトリ一覧表示フラグを反転
	m_isDirListing = m_isDirListing ? false : true;
	
	//テーブル再読み込み：アニメーションあり
	pSections = [NSIndexSet indexSetWithIndexesInRange:range];
	[m_pTableView reloadSections:pSections withRowAnimation:UITableViewRowAnimationAutomatic];
	
EXIT:;
	if (result != 0) YN_SHOW_ERR();
	return;
}

//******************************************************************************
// Saveボタン選択イベント
//******************************************************************************
- (void)onSaveButton:(id)sender
{
	NSIndexPath *pIndexPath = nil;
	UITableViewCell* pCell = nil;
	UITextField* pTextField = nil;
	UIAlertController* pAlertController = nil;
	UIAlertAction* pAlertAction = nil;
	
	//編集されたファイル名を取得
	pIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
	pCell = [m_pTableView cellForRowAtIndexPath:pIndexPath];
	pTextField = (UITextField*)[pCell.contentView viewWithTag:1];
	m_pNewFileName = pTextField.text;
	[m_pNewFileName retain];
	
	//ファイル名不正チェック
	if (([m_pNewFileName length] == 0) || ([m_pNewFileName containsString:@"/"])) {
		//ファイル名不正アラート表示
		pAlertController = [UIAlertController alertControllerWithTitle:@"Confirmation"
															   message:@"Please enter a valid name."
														preferredStyle:UIAlertControllerStyleAlert];
		pAlertAction = [UIAlertAction actionWithTitle:@"OK"
												style:UIAlertActionStyleDefault
											  handler:nil];
		[pAlertController addAction:pAlertAction];
		[self presentViewController:pAlertController animated:YES completion:nil];
		goto EXIT;
	}
	//保存確認アラート表示
	pAlertController = [UIAlertController alertControllerWithTitle:@"Confirmation"
														   message:@"Do you want to save changes?"
													preferredStyle:UIAlertControllerStyleAlert];
	pAlertAction = [UIAlertAction actionWithTitle:@"Yes"
											style:UIAlertActionStyleDefault
										  handler:^(UIAlertAction *action) {[self onAlertSaveYes];}];
	[pAlertController addAction:pAlertAction];
	pAlertAction = [UIAlertAction actionWithTitle:@"Cancel"
											style:UIAlertActionStyleDefault
										  handler:^(UIAlertAction *action) {[self onAlertSaveCancel];}];
	[pAlertController addAction:pAlertAction];
	[self presentViewController:pAlertController animated:YES completion:nil];
	
EXIT:;
	return;
}

//******************************************************************************
// 保存確認Yesボタン押下
//******************************************************************************
- (void)onAlertSaveYes
{
	if (m_isCreatingDir) {
		//ディレクトリ作成通知
		[self postNotificationWithName:m_pNotificationNameForCreateDir];
	}
	else {
		//ファイル編集通知
		[self postNotificationWithName:m_pNotificationNameForEditFile];
	}
	
	//1階層戻る
	[self.navigationController popViewControllerAnimated:YES];
	
	return;
}

//******************************************************************************
// 保存確認Cancelボタン押下
//******************************************************************************
- (void)onAlertSaveCancel
{
	//何もしない
	return;
}

//******************************************************************************
// 通知送信処理
//******************************************************************************
- (int)postNotificationWithName:(NSString*)pName
{
	int result = 0;
	NSNotification* pNotification = nil;
	NSNotificationCenter* pCenter = nil;
	
	//通知オブジェクトを作成
	pNotification = [NSNotification notificationWithName:pName
												  object:self
												userInfo:nil];
	//通知する
	pCenter = [NSNotificationCenter defaultCenter];
	
	//通知に対応する処理を演奏スレッドで処理させる場合
	//[pCenter postNotification:pNotification];
	
	//通知に対応する処理をメインスレッドに処理させる場合
	[pCenter performSelectorOnMainThread:@selector(postNotification:)
							  withObject:pNotification
						   waitUntilDone:NO];
	
	return result;
}

//******************************************************************************
// 新ファイル名取得
//******************************************************************************
- (NSString*)getNewFileName
{
	NSString* pNewFileNameWithExtension = nil;
	
	//編集後のファイル名に拡張子を付与
	pNewFileNameWithExtension = m_pNewFileName;
	if ([m_pExtension length] > 0) {
		pNewFileNameWithExtension = [m_pNewFileName stringByAppendingPathExtension:m_pExtension];
	}
	
	return pNewFileNameWithExtension;
}

//******************************************************************************
// 新ファイルパス取得
//******************************************************************************
- (NSString*)getNewFilePath
{
	NSString* pNewFileNameWithExtension = nil;
	NSString* pNewFilePath = nil;
	
	//編集後のファイル名に拡張子を付与
	pNewFileNameWithExtension = m_pNewFileName;
	if ([m_pExtension length] > 0) {
		pNewFileNameWithExtension = [m_pNewFileName stringByAppendingPathExtension:m_pExtension];
	}
	
	//新ファイルパス
	pNewFilePath = [m_pSelectedDirPath stringByAppendingPathComponent:pNewFileNameWithExtension];
	
	return pNewFilePath;
}

//******************************************************************************
// ディレクトリ一覧生成
//******************************************************************************
- (int)makeDirectoryList
{
	int result = 0;
	
	//ディレクトリ配列の先頭に対象ディレクトリを追加
	[m_pDirPathList release];
	m_pDirPathList = [[NSMutableArray alloc] init];
	[m_pDirPathList addObject:m_pDocumentsDirPath];
	
	//ディレクトリ配下のディレクトリを再帰的にリスト登録
	result = [self searchDirectoriesForPath:m_pDocumentsDirPath directoryArray:m_pDirPathList];
	
	return result;
}

//******************************************************************************
// ディレクトリ検索
//******************************************************************************
- (int)searchDirectoriesForPath:(NSString*)pTargetDirPath directoryArray:(NSMutableArray*)pDirectoryArray
{
	int result = 0;
	NSArray* pFileArrayTmp = nil;
	NSMutableArray* pDirectoryArrayTmp = nil;
	NSString* pFile = nil;
	NSString* pDirectory = nil;
	NSString* pPath = nil;
	BOOL isDir = NO;
	int i = 0;
	
	//NSLog(@"%@", pTargetDirPath);
	
	//対象ディレクトリ配下のファイル一覧を取得
	if ([[NSFileManager defaultManager] fileExistsAtPath:pTargetDirPath]) {
		pFileArrayTmp = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:pTargetDirPath error:nil];
	}
	else {
		//ディレクトリが存在しない場合は何もせず終了
		goto EXIT;
	}
	
	//ディレクトリ一覧を作成
	pDirectoryArrayTmp = [[NSMutableArray alloc] init];
	for (i = 0; i < [pFileArrayTmp count]; i++) {
		pFile = [pFileArrayTmp objectAtIndex:i];
		pPath = [pTargetDirPath stringByAppendingPathComponent:pFile];
		if ([[NSFileManager defaultManager] fileExistsAtPath:pPath isDirectory:&isDir]) {
			if (isDir) {
				//ディレクトリの場合
				if ([pFile isEqualToString:@"Inbox"]
					|| [pFile isEqualToString:@".Trash"]) {
					//Inboxディレクトリとゴミ箱ディレクトリは除外
					continue;
				}
				if ([pPath isEqualToString:[m_pCurrentDirPath stringByAppendingPathComponent:m_pFileName]]) {
					//指定されたディレクトリと一致している場合は移動先にできないので除外（その配下のディレクトリも除外）
					continue;
				}
				[pDirectoryArrayTmp addObject:pFile];
			}
		}
		else {
			NSLog(@"%@", pPath);
			NSLog(@"NOT EXIST!");
		}
	}
	
	//ディレクトリ名ソート：大文字小文字を区別しない
	[pDirectoryArrayTmp sortUsingComparator:^(id str1, id str2) {
		return [((NSString*)str1) compare:((NSString*)str2) options:NSCaseInsensitiveSearch]; }];
	
	//ディレクトリ配下のディレクトリを再帰的に確認
	for (i = 0; i < [pDirectoryArrayTmp count]; i++) {
		pDirectory = [pDirectoryArrayTmp objectAtIndex:i];
		pPath = [pTargetDirPath stringByAppendingPathComponent:pDirectory];
		
		//ディレクトリ一覧に指定されたディレクトリを追加
		[pDirectoryArray addObject:pPath];
		
		//ディレクトリ配下のディレクトリを再帰的にリスト登録
		result = [self searchDirectoriesForPath:pPath directoryArray:pDirectoryArray];
		if (result != 0) goto EXIT;
	}
	
EXIT:;
	[pDirectoryArrayTmp release];
	return result;
}

//******************************************************************************
// 破棄
//******************************************************************************
- (void)dealloc
{
	//NSLog(@"MTFileEditViewCtrl::dealloc %@", self.title);
	
	[m_pFileName release];
	[m_pExtension release];
	[m_pCurrentDirPath release];
	[m_pSelectedDirPath release];
	[m_pNewFileName release];
	[m_pNotificationNameForEditFile release];
	[m_pNotificationNameForCreateDir release];
	[m_pDirPathList release];
	[m_pDocumentsDirPath release];
	
	m_pFileName = nil;
	m_pExtension = nil;
	m_pCurrentDirPath = nil;
	m_pSelectedDirPath = nil;
	m_pNewFileName = nil;
	m_pNotificationNameForEditFile = nil;
	m_pNotificationNameForCreateDir = nil;
	m_pDirPathList = nil;
	m_pDocumentsDirPath = nil;
	
	[super dealloc];
	
	return;
}

@end

