module Pod
  class LocalPod
    attr_reader :specification
    
    def initialize(specification, sandbox)
      @specification, @sandbox = specification, sandbox
    end
    
    def self.from_podspec(podspec, sandbox)
      new(Specification.from_file(podspec), sandbox)
    end
    
    def root
      @sandbox.root + specification.name
    end
    
    def to_s
      if specification.local?
        "#{specification} [LOCAL]"
      else
        specification.to_s
      end
    end
    
    def name
      specification.name
    end
    
    def create
      root.mkpath unless exists?
    end
    
    def exists?
      root.exist?
    end
    
    def chdir(&block)
      create
      Dir.chdir(root, &block)
    end
    
    def implode
      root.rmtree if exists?
    end
    
    def clean
      clean_paths.each { |path| FileUtils.rm_rf(path) }
    end
    
    def source_files
      expanded_paths(specification.source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => true)
    end
    
    def clean_paths
      expanded_paths(specification.clean_paths)
    end
    
    def resources
      expanded_paths(specification.resources, :relative_to_sandbox => true)
    end

    def header_files
      source_files.select { |f| f.extname == '.h' }
    end
    
    def link_headers
      copy_header_mappings.each do |namespaced_path, files|
        @sandbox.add_header_files(namespaced_path, files)
      end
    end
    
    def add_to_target(target)
      implementation_files.each do |file|
        target.add_source_file(file, nil, specification.compiler_flags)
      end
    end

    # Generates and installs the documentation of the pod.
    #
    # It returns a human redable string containing the source used
    # for the documentation. If no source was available it returns
    # nil.
    #
    def generate_documentation(install, force = true, verbose = false)
      documentation = specification.documentation ? specification.documentation : {}

      if force || documentation.has_key?(:appledoc)
          `which appledoc`
          return nil unless $?.success?
          dir = "#{@sandbox.root}/Documentation/#{name}/"
          FileUtils.mkdir_p(dir)
          # default options
          options = ['--project-name', specification.to_s,
                      '--project-company', specification.authors.keys.to_s,
                      '--docset-copyright', "Generated by cocoapods (see #{specification.homepage} for copyright information).",
                      '--docset-desc', specification.description,
                      '--company-id', 'org.cocoapods',
                      '--ignore', '.m']
          # spec options
          options += documentation[:appledoc] if documentation[:appledoc]
          # options that can't be overridden
          options << '--no-create-docset' unless install
          options << '--keep-intermediate-files'
          options += ['--print-settings'] if verbose
          options += ['--output', dir]
          options += expanded_paths(specification.source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => false)
          success = false
          Open3.popen3('appledoc', *options ) do |stdin, stdout, stderr|
            puts stdout.read.chomp if verbose
            puts stderr.read.chomp if verbose
            success = stderr.read.chomp == ""
          end
          # TODO: should return nil if appledoc fails
          return success ? 'appledoc' : nil

        elsif documentation[:atom] && install
          # TODO: donwload and uncompress the docset
          # path =
          #Open3.popen3('osascript') { |stdin, stdout, stderr|
          #stdin.puts('tell application "Xcode"')
          #stdin.puts("load documentation set with path \"#{path}\"")
          #stdin.puts('end tell')
          #stdin.close
          #puts stdout.read.chomp if verbose
          #puts stderr.read.chomp if verbose
          #}
          #return 'atom'
        end
      return nil
    end

    def requires_arc?
      specification.requires_arc
    end
    
    private
    
    def implementation_files
      source_files.select { |f| f.extname != '.h' }
    end
    
    def relative_root
      root.relative_path_from(@sandbox.root)
    end
    
    def copy_header_mappings
      header_files.inject({}) do |mappings, from|
        from_without_prefix = from.relative_path_from(relative_root)
        to = specification.header_dir + specification.copy_header_mapping(from_without_prefix)
        (mappings[to.dirname] ||= []) << from
        mappings
      end
    end
    
    def expanded_paths(patterns, options={})
      patterns.map do |pattern|
        pattern = root + pattern
        
        if pattern.directory? && options[:glob]
          pattern += options[:glob]
        end
        
        pattern.glob.map do |file| 
          if options[:relative_to_sandbox]
            file.relative_path_from(@sandbox.root)
          else
            file
          end
        end
      end.flatten
    end
  end
end

