// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/shell_dialogs/select_file_dialog_mac.h"

#include <CoreServices/CoreServices.h>
#include <stddef.h>

#include <vector>

#include "base/files/file_util.h"
#include "base/i18n/case_conversion.h"
#include "base/logging.h"
#include "base/mac/bundle_locations.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#import "ui/base/cocoa/nib_loading.h"
#include "ui/base/l10n/l10n_util_mac.h"
#include "ui/strings/grit/ui_strings.h"

namespace {

const int kFileTypePopupTag = 1234;

CFStringRef CreateUTIFromExtension(const base::FilePath::StringType& ext) {
  base::ScopedCFTypeRef<CFStringRef> ext_cf(base::SysUTF8ToCFStringRef(ext));
  return UTTypeCreatePreferredIdentifierForTag(
      kUTTagClassFilenameExtension, ext_cf.get(), NULL);
}

NSString* GetDescriptionFromExtension(const base::FilePath::StringType& ext) {
  base::ScopedCFTypeRef<CFStringRef> uti(CreateUTIFromExtension(ext));
  base::ScopedCFTypeRef<CFStringRef> description(
      UTTypeCopyDescription(uti.get()));

  if (description && CFStringGetLength(description))
    return [[base::mac::CFToNSCast(description.get()) retain] autorelease];

  // In case no description is found, create a description based on the
  // unknown extension type (i.e. if the extension is .qqq, the we create
  // a description "QQQ File (.qqq)").
  base::string16 ext_name = base::UTF8ToUTF16(ext);
  return l10n_util::GetNSStringF(IDS_APP_SAVEAS_EXTENSION_FORMAT,
                                 base::i18n::ToUpper(ext_name), ext_name);
}

}  // namespace

// A bridge class to act as the modal delegate to the save/open sheet and send
// the results to the C++ class.
@interface SelectFileDialogBridge : NSObject<NSOpenSavePanelDelegate> {
 @private
  ui::SelectFileDialogImpl* selectFileDialogImpl_;  // WEAK; owns us
}

- (id)initWithSelectFileDialogImpl:(ui::SelectFileDialogImpl*)s;
- (void)endedPanel:(NSSavePanel*)panel
         didCancel:(bool)did_cancel
              type:(ui::SelectFileDialog::Type)type
      parentWindow:(NSWindow*)parentWindow;

// NSSavePanel delegate method
- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url;

@end

// Target for NSPopupButton control in file dialog's accessory view.
@interface ExtensionDropdownHandler : NSObject {
 @private
  // The file dialog to which this target object corresponds. Weak reference
  // since the dialog_ will stay alive longer than this object.
  NSSavePanel* dialog_;

  // An array whose each item corresponds to an array of different extensions in
  // an extension group.
  base::scoped_nsobject<NSArray> fileTypeLists_;
}

- (id)initWithDialog:(NSSavePanel*)dialog fileTypeLists:(NSArray*)fileTypeLists;

- (void)popupAction:(id)sender;
@end

namespace ui {

SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener,
                                           ui::SelectFilePolicy* policy)
    : SelectFileDialog(listener, policy),
      bridge_([[SelectFileDialogBridge alloc]
               initWithSelectFileDialogImpl:this]) {
}

bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const {
  return parents_.find(parent_window) != parents_.end();
}

void SelectFileDialogImpl::ListenerDestroyed() {
  listener_ = NULL;
}

void SelectFileDialogImpl::FileWasSelected(
    NSSavePanel* dialog,
    NSWindow* parent_window,
    bool was_cancelled,
    bool is_multi,
    const std::vector<base::FilePath>& files,
    int index) {
  parents_.erase(parent_window);

  auto it = dialog_data_map_.find(dialog);
  DCHECK(it != dialog_data_map_.end());
  void* params = it->second.params;
  dialog_data_map_.erase(it);

  [dialog setDelegate:nil];

  if (!listener_)
    return;

  if (was_cancelled || files.empty()) {
    listener_->FileSelectionCanceled(params);
  } else {
    if (is_multi) {
      listener_->MultiFilesSelected(files, params);
    } else {
      listener_->FileSelected(files[0], index, params);
    }
  }
}

void SelectFileDialogImpl::SelectFileImpl(
    Type type,
    const base::string16& title,
    const base::FilePath& default_path,
    const FileTypeInfo* file_types,
    int file_type_index,
    const base::FilePath::StringType& default_extension,
    gfx::NativeWindow owning_window,
    void* params) {
  DCHECK(type == SELECT_FOLDER ||
         type == SELECT_UPLOAD_FOLDER ||
         type == SELECT_OPEN_FILE ||
         type == SELECT_OPEN_MULTI_FILE ||
         type == SELECT_SAVEAS_FILE);
  parents_.insert(owning_window);

  // Note: we need to retain the dialog as owning_window can be null.
  // (See http://crbug.com/29213 .)
  NSSavePanel* dialog;
  if (type == SELECT_SAVEAS_FILE)
    dialog = [[NSSavePanel savePanel] retain];
  else
    dialog = [[NSOpenPanel openPanel] retain];

  if (!title.empty())
    [dialog setMessage:base::SysUTF16ToNSString(title)];

  NSString* default_dir = nil;
  NSString* default_filename = nil;
  if (!default_path.empty()) {
    // The file dialog is going to do a ton of stats anyway. Not much
    // point in eliminating this one.
    base::ThreadRestrictions::ScopedAllowIO allow_io;
    if (base::DirectoryExists(default_path)) {
      default_dir = base::SysUTF8ToNSString(default_path.value());
    } else {
      default_dir = base::SysUTF8ToNSString(default_path.DirName().value());
      default_filename =
          base::SysUTF8ToNSString(default_path.BaseName().value());
    }
  }

  base::scoped_nsobject<ExtensionDropdownHandler> handler;
  if (type != SELECT_FOLDER && type != SELECT_UPLOAD_FOLDER) {
    if (file_types) {
      handler = SelectFileDialogImpl::SetAccessoryView(
          dialog, file_types, file_type_index, default_extension);
    } else {
      // If no type info is specified, anything goes.
      [dialog setAllowsOtherFileTypes:YES];
    }
  }

  auto inserted = dialog_data_map_.insert(
      std::make_pair(dialog, DialogData(params, handler)));
  DCHECK(inserted.second);  // Dialog should never exist already.

  hasMultipleFileTypeChoices_ =
      file_types ? file_types->extensions.size() > 1 : true;

  if (type == SELECT_SAVEAS_FILE) {
    // When file extensions are hidden and removing the extension from
    // the default filename gives one which still has an extension
    // that OS X recognizes, it will get confused and think the user
    // is trying to override the default extension. This happens with
    // filenames like "foo.tar.gz" or "ball.of.tar.png". Work around
    // this by never hiding extensions in that case.
    base::FilePath::StringType penultimate_extension =
        default_path.RemoveFinalExtension().FinalExtension();
    if (!penultimate_extension.empty() &&
        penultimate_extension.length() <= 5U) {
      [dialog setExtensionHidden:NO];
    } else {
      [dialog setCanSelectHiddenExtension:YES];
    }
  } else {
    NSOpenPanel* open_dialog = (NSOpenPanel*)dialog;

    if (type == SELECT_OPEN_MULTI_FILE)
      [open_dialog setAllowsMultipleSelection:YES];
    else
      [open_dialog setAllowsMultipleSelection:NO];

    if (type == SELECT_FOLDER || type == SELECT_UPLOAD_FOLDER) {
      [open_dialog setCanChooseFiles:NO];
      [open_dialog setCanChooseDirectories:YES];
      [open_dialog setCanCreateDirectories:YES];
      NSString *prompt = (type == SELECT_UPLOAD_FOLDER)
          ? l10n_util::GetNSString(IDS_SELECT_UPLOAD_FOLDER_BUTTON_TITLE)
          : l10n_util::GetNSString(IDS_SELECT_FOLDER_BUTTON_TITLE);
      [open_dialog setPrompt:prompt];
    } else {
      [open_dialog setCanChooseFiles:YES];
      [open_dialog setCanChooseDirectories:NO];
    }

    [open_dialog setDelegate:bridge_.get()];
  }
  if (default_dir)
    [dialog setDirectoryURL:[NSURL fileURLWithPath:default_dir]];
  if (default_filename)
    [dialog setNameFieldStringValue:default_filename];
  [dialog beginSheetModalForWindow:owning_window
                 completionHandler:^(NSInteger result) {
    [bridge_.get() endedPanel:dialog
                    didCancel:result != NSFileHandlingPanelOKButton
                         type:type
                 parentWindow:owning_window];
  }];
}

SelectFileDialogImpl::DialogData::DialogData(
    void* params_,
    base::scoped_nsobject<ExtensionDropdownHandler> handler)
    : params(params_), extension_dropdown_handler(handler) {}

SelectFileDialogImpl::DialogData::DialogData(const DialogData& other) = default;

SelectFileDialogImpl::DialogData::~DialogData() {}

SelectFileDialogImpl::~SelectFileDialogImpl() {
  // Walk through the open dialogs and close them all.  Use a temporary vector
  // to hold the pointers, since we can't delete from the map as we're iterating
  // through it.
  std::vector<NSSavePanel*> panels;
  for (const auto& value : dialog_data_map_)
    panels.push_back(value.first);

  for (const auto& panel : panels)
    [panel cancel:panel];
}

// static
base::scoped_nsobject<ExtensionDropdownHandler>
SelectFileDialogImpl::SetAccessoryView(
    NSSavePanel* dialog,
    const FileTypeInfo* file_types,
    int file_type_index,
    const base::FilePath::StringType& default_extension) {
  DCHECK(file_types);
  NSView* accessory_view = ui::GetViewFromNib(@"SaveAccessoryView");
  if (!accessory_view)
    return base::scoped_nsobject<ExtensionDropdownHandler>();
  [dialog setAccessoryView:accessory_view];

  NSPopUpButton* popup = [accessory_view viewWithTag:kFileTypePopupTag];
  DCHECK(popup);

  // Create an array with each item corresponding to an array of different
  // extensions in an extension group.
  NSMutableArray* file_type_lists = [NSMutableArray array];
  int default_extension_index = -1;
  for (size_t i = 0; i < file_types->extensions.size(); ++i) {
    const std::vector<base::FilePath::StringType>& ext_list =
        file_types->extensions[i];

    // Generate type description for the extension group.
    NSString* type_description = nil;
    if (i < file_types->extension_description_overrides.size() &&
        !file_types->extension_description_overrides[i].empty()) {
      type_description = base::SysUTF16ToNSString(
          file_types->extension_description_overrides[i]);
    } else {
      // No description given for a list of extensions; pick the first one
      // from the list (arbitrarily) and use its description.
      DCHECK(!ext_list.empty());
      type_description = GetDescriptionFromExtension(ext_list[0]);
    }
    DCHECK_NE(0u, [type_description length]);
    [popup addItemWithTitle:type_description];

    // Populate file_type_lists.
    // Set to store different extensions in the current extension group.
    NSMutableSet* file_type_set = [NSMutableSet set];
    for (const base::FilePath::StringType& ext : ext_list) {
      if (ext == default_extension)
        default_extension_index = i;

      // Crash reports suggest that CreateUTIFromExtension may return nil. Hence
      // we nil check before adding to |file_type_set|. See crbug.com/630101 and
      // rdar://27490414.
      base::ScopedCFTypeRef<CFStringRef> uti(CreateUTIFromExtension(ext));
      if (uti)
        [file_type_set addObject:base::mac::CFToNSCast(uti.get())];

      // Always allow the extension itself, in case the UTI doesn't map
      // back to the original extension correctly. This occurs with dynamic
      // UTIs on 10.7 and 10.8.
      // See http://crbug.com/148840, http://openradar.me/12316273
      base::ScopedCFTypeRef<CFStringRef> ext_cf(
          base::SysUTF8ToCFStringRef(ext));
      [file_type_set addObject:base::mac::CFToNSCast(ext_cf.get())];
    }
    [file_type_lists addObject:[file_type_set allObjects]];
  }

  if (file_types->include_all_files || file_types->extensions.empty()) {
    [popup addItemWithTitle:l10n_util::GetNSString(IDS_APP_SAVEAS_ALL_FILES)];
    [dialog setAllowsOtherFileTypes:YES];
  }

  base::scoped_nsobject<ExtensionDropdownHandler> handler(
      [[ExtensionDropdownHandler alloc] initWithDialog:dialog
                                         fileTypeLists:file_type_lists]);

  // This establishes a weak reference to handler. Hence we persist it as part
  // of dialog_data_map_.
  [popup setTarget:handler];
  [popup setAction:@selector(popupAction:)];

  // file_type_index uses 1 based indexing.
  if (file_type_index) {
    DCHECK_LE(static_cast<size_t>(file_type_index),
              file_types->extensions.size());
    DCHECK_GE(file_type_index, 1);
    [popup selectItemAtIndex:file_type_index - 1];
    [handler popupAction:popup];
  } else if (!default_extension.empty() && default_extension_index != -1) {
    [popup selectItemAtIndex:default_extension_index];
    [dialog
        setAllowedFileTypes:@[ base::SysUTF8ToNSString(default_extension) ]];
  } else {
    // Select the first item.
    [popup selectItemAtIndex:0];
    [handler popupAction:popup];
  }

  return handler;
}

bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() {
  return hasMultipleFileTypeChoices_;
}

SelectFileDialog* CreateSelectFileDialog(SelectFileDialog::Listener* listener,
                                         SelectFilePolicy* policy) {
  return new SelectFileDialogImpl(listener, policy);
}

}  // namespace ui

@implementation SelectFileDialogBridge

- (id)initWithSelectFileDialogImpl:(ui::SelectFileDialogImpl*)s {
  if ((self = [super init])) {
    selectFileDialogImpl_ = s;
  }
  return self;
}

- (void)endedPanel:(NSSavePanel*)panel
         didCancel:(bool)did_cancel
              type:(ui::SelectFileDialog::Type)type
      parentWindow:(NSWindow*)parentWindow {
  int index = 0;
  std::vector<base::FilePath> paths;
  if (!did_cancel) {
    if (type == ui::SelectFileDialog::SELECT_SAVEAS_FILE) {
      if ([[panel URL] isFileURL]) {
        paths.push_back(base::mac::NSStringToFilePath([[panel URL] path]));
      }

      NSView* accessoryView = [panel accessoryView];
      if (accessoryView) {
        NSPopUpButton* popup = [accessoryView viewWithTag:kFileTypePopupTag];
        if (popup) {
          // File type indexes are 1-based.
          index = [popup indexOfSelectedItem] + 1;
        }
      } else {
        index = 1;
      }
    } else {
      CHECK([panel isKindOfClass:[NSOpenPanel class]]);
      NSArray* urls = [static_cast<NSOpenPanel*>(panel) URLs];
      for (NSURL* url in urls)
        if ([url isFileURL])
          paths.push_back(base::FilePath(base::SysNSStringToUTF8([url path])));
    }
  }

  bool isMulti = type == ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE;
  selectFileDialogImpl_->FileWasSelected(panel,
                                         parentWindow,
                                         did_cancel,
                                         isMulti,
                                         paths,
                                         index);
  [panel release];
}

- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url {
  return [url isFileURL];
}

@end

@implementation ExtensionDropdownHandler

- (id)initWithDialog:(NSSavePanel*)dialog
       fileTypeLists:(NSArray*)fileTypeLists {
  if ((self = [super init])) {
    dialog_ = dialog;
    fileTypeLists_.reset([fileTypeLists retain]);
  }
  return self;
}

- (void)popupAction:(id)sender {
  NSUInteger index = [sender indexOfSelectedItem];
  if (index < [fileTypeLists_ count]) {
    // For save dialogs, this causes the first item in the allowedFileTypes
    // array to be used as the extension for the save panel.
    [dialog_ setAllowedFileTypes:[fileTypeLists_ objectAtIndex:index]];
  } else {
    // The user selected "All files" option.
    [dialog_ setAllowedFileTypes:nil];
  }
}

@end
