/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2012 Nicolas Despres <nicolas.despres@gmail.com>

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
#include "cmOSXBundleGenerator.h"

#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmTarget.h"

#include <cassert>

cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target,
                                           const std::string& configName)
  : GT(target)
  , Makefile(target->Target->GetMakefile())
  , LocalGenerator(target->GetLocalGenerator())
  , ConfigName(configName)
  , MacContentFolders(0)
{
  if (this->MustSkip())
    return;
}

bool cmOSXBundleGenerator::MustSkip()
{
  return !this->GT->HaveWellDefinedOutputFiles();
}

void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
                                           std::string& outpath)
{
  if (this->MustSkip())
    return;

  // Compute bundle directory names.
  std::string out = outpath;
  out += "/";
  out += this->GT->GetAppBundleDirectory(this->ConfigName, false);
  cmSystemTools::MakeDirectory(out.c_str());
  this->Makefile->AddCMakeOutputFile(out);

  std::string newoutpath = out;

  // Configure the Info.plist file.  Note that it needs the executable name
  // to be set.
  std::string plist = outpath;
  plist += "/";
  plist += this->GT->GetAppBundleDirectory(this->ConfigName, true);
  plist += "/Info.plist";
  this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName,
                                               plist.c_str());
  this->Makefile->AddCMakeOutputFile(plist);
  outpath = newoutpath;
}

void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
                                           const std::string& outpath)
{
  if (this->MustSkip())
    return;

  assert(this->MacContentFolders);

  // Compute the location of the top-level foo.framework directory.
  std::string contentdir =
    outpath + "/" + this->GT->GetFrameworkDirectory(this->ConfigName, true);
  contentdir += "/";

  std::string newoutpath =
    outpath + "/" + this->GT->GetFrameworkDirectory(this->ConfigName, false);

  std::string frameworkVersion = this->GT->GetFrameworkVersion();

  // Configure the Info.plist file
  std::string plist = newoutpath;
  if (!this->Makefile->PlatformIsAppleIos()) {
    // Put the Info.plist file into the Resources directory.
    this->MacContentFolders->insert("Resources");
    plist += "/Resources";
  }
  plist += "/Info.plist";
  std::string name = cmSystemTools::GetFilenameName(targetName);
  this->LocalGenerator->GenerateFrameworkInfoPList(this->GT, name,
                                                   plist.c_str());

  // Generate Versions directory only for MacOSX frameworks
  if (this->Makefile->PlatformIsAppleIos())
    return;

  // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
  // drive rules to create these files at build time.
  std::string oldName;
  std::string newName;

  // Make foo.framework/Versions
  std::string versions = contentdir;
  versions += "Versions";
  cmSystemTools::MakeDirectory(versions.c_str());

  // Make foo.framework/Versions/version
  cmSystemTools::MakeDirectory(newoutpath.c_str());

  // Current -> version
  oldName = frameworkVersion;
  newName = versions;
  newName += "/Current";
  cmSystemTools::RemoveFile(newName);
  cmSystemTools::CreateSymlink(oldName, newName);
  this->Makefile->AddCMakeOutputFile(newName);

  // foo -> Versions/Current/foo
  oldName = "Versions/Current/";
  oldName += name;
  newName = contentdir;
  newName += name;
  cmSystemTools::RemoveFile(newName);
  cmSystemTools::CreateSymlink(oldName, newName);
  this->Makefile->AddCMakeOutputFile(newName);

  // Resources -> Versions/Current/Resources
  if (this->MacContentFolders->find("Resources") !=
      this->MacContentFolders->end()) {
    oldName = "Versions/Current/Resources";
    newName = contentdir;
    newName += "Resources";
    cmSystemTools::RemoveFile(newName);
    cmSystemTools::CreateSymlink(oldName, newName);
    this->Makefile->AddCMakeOutputFile(newName);
  }

  // Headers -> Versions/Current/Headers
  if (this->MacContentFolders->find("Headers") !=
      this->MacContentFolders->end()) {
    oldName = "Versions/Current/Headers";
    newName = contentdir;
    newName += "Headers";
    cmSystemTools::RemoveFile(newName);
    cmSystemTools::CreateSymlink(oldName, newName);
    this->Makefile->AddCMakeOutputFile(newName);
  }

  // PrivateHeaders -> Versions/Current/PrivateHeaders
  if (this->MacContentFolders->find("PrivateHeaders") !=
      this->MacContentFolders->end()) {
    oldName = "Versions/Current/PrivateHeaders";
    newName = contentdir;
    newName += "PrivateHeaders";
    cmSystemTools::RemoveFile(newName);
    cmSystemTools::CreateSymlink(oldName, newName);
    this->Makefile->AddCMakeOutputFile(newName);
  }
}

void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
                                          const std::string& root)
{
  if (this->MustSkip())
    return;

  // Compute bundle directory names.
  std::string out = root;
  out += "/";
  out += this->GT->GetCFBundleDirectory(this->ConfigName, false);
  cmSystemTools::MakeDirectory(out.c_str());
  this->Makefile->AddCMakeOutputFile(out);

  // Configure the Info.plist file.  Note that it needs the executable name
  // to be set.
  std::string plist =
    root + "/" + this->GT->GetCFBundleDirectory(this->ConfigName, true);
  plist += "/Info.plist";
  std::string name = cmSystemTools::GetFilenameName(targetName);
  this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist.c_str());
  this->Makefile->AddCMakeOutputFile(plist);
}

void cmOSXBundleGenerator::GenerateMacOSXContentStatements(
  std::vector<cmSourceFile const*> const& sources,
  MacOSXContentGeneratorType* generator)
{
  if (this->MustSkip())
    return;

  for (std::vector<cmSourceFile const*>::const_iterator si = sources.begin();
       si != sources.end(); ++si) {
    cmGeneratorTarget::SourceFileFlags tsFlags =
      this->GT->GetTargetSourceFileFlags(*si);
    if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) {
      (*generator)(**si, tsFlags.MacFolder);
    }
  }
}

std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(
  const char* pkgloc)
{
  // Construct the full path to the content subdirectory.

  std::string macdir = this->GT->GetMacContentDirectory(this->ConfigName,
                                                        /*implib*/ false);
  macdir += "/";
  macdir += pkgloc;
  cmSystemTools::MakeDirectory(macdir.c_str());

  // Record use of this content location.  Only the first level
  // directory is needed.
  {
    std::string loc = pkgloc;
    loc = loc.substr(0, loc.find('/'));
    this->MacContentFolders->insert(loc);
  }

  return macdir;
}
