# encoding: utf-8
module Middleman
  module Presentation
    module Cli
      # Initialize presentation
      class CreatePresentation < Thor::Group
        include Thor::Actions

        class_option :speaker, required: true, default: Middleman::Presentation.config.speaker, desc: 'Name of speaker'
        class_option :title, required: true, desc: 'Title of presentation'
        class_option :date, required: true, default: Time.now.strftime('%d.%m.%Y'), desc: 'Date of presentation'
        class_option :license, required: true, default: Middleman::Presentation.config.license, desc: 'License of the presentation, e.g. CC BY'

        class_option :bower_directory, default: Middleman::Presentation.config.bower_directory, desc: 'Directory for bower components in "source"-directory'
        class_option :author, default: Middleman::Presentation.config.author, desc: 'Author of presentation'
        class_option :description, desc: 'Description for presentation'
        class_option :subtitle, desc: 'Subtitle of presentation'
        class_option :homepage, default: Middleman::Presentation.config.homepage, desc: 'Homepage of company and/or speaker'
        class_option :company, default: Middleman::Presentation.config.company, desc: 'Company or employer or organization of speaker'
        class_option :location, default: Middleman::Presentation.config.location, desc: 'Location where the presentation take place'
        class_option :audience, default: Middleman::Presentation.config.audience, desc: 'Audience of presentation'

        class_option :phone_number, default: Middleman::Presentation.config.phone_number, desc: 'Phone number to contact speaker'
        class_option :email_address, default: Middleman::Presentation.config.email_address, desc: 'Email address to contact speaker'
        class_option :github_url, default: Middleman::Presentation.config.github_url, desc: 'Url to Github account of speaker'

        class_option :activate_controls, type: :boolean, default: Middleman::Presentation.config.activate_controls, desc: 'Activate controls in reveal.js'
        class_option :activate_progress, type: :boolean, default: Middleman::Presentation.config.activate_progress, desc: 'Activate progress in reveal.js'
        class_option :activate_history, type: :boolean, default: Middleman::Presentation.config.activate_history, desc: 'Activate history in reveal.js'
        class_option :activate_center, type: :boolean, default: Middleman::Presentation.config.activate_center, desc: 'Activate center in reveal.js'
        class_option :activate_slide_number, type: :boolean, default: Middleman::Presentation.config.activate_slide_number, desc: 'Activate slide number in reveal.js'

        class_option :default_transition_type, default: Middleman::Presentation.config.default_transition_type, desc: 'Default slide transition. Can be overwridden per slide.'
        class_option :default_transition_speed, default: Middleman::Presentation.config.default_transition_speed, desc: 'Default speed for slide transition. Can be overwridden per slide.'

        class_option :install_assets, type: :boolean, default: Middleman::Presentation.config.install_assets, desc: 'Install assets'
        class_option :initialize_git, type: :boolean, default: Middleman::Presentation.config.initialize_git, desc: 'Initialize git repository'
        class_option :check_for_bower, type: :boolean, default: Middleman::Presentation.config.check_for_bower, desc: 'Check if bower is installed on the system'

        class_option :create_predefined_slides, type: :boolean, default: Middleman::Presentation.config.create_predefined_slides, desc: 'Install predefined slides'

        class_option :language, type: :array, desc: 'Language to use for translatable slide templates, e.g. "de", "en"'
        class_option :version, default: Middleman::Presentation.config.default_version_number, desc: 'Version number for your presentation'

        argument :directory, default: Dir.getwd, desc: 'Directory to create presentation in'
        desc 'Initialize a new presentation in DIR (default: $PWD)'

        def define_root_directory
          @root_directory = File.expand_path directory
        end

        def add_to_source_path
          source_paths << File.expand_path('../../../../templates', __FILE__)
        end

        def initialize_middleman
          run("middleman init --skip-bundle --template empty #{directory}")
          fail Thor::Error, 'Error executing `middleman init`-command. Please fix your setup and run again.' unless $CHILD_STATUS.exitstatus == 0
        end

        def set_language
          language_detector = FeduxOrgStdlib::ShellLanguageDetector.new
          language = language_detector.detect allowed: I18n.available_locales, overwrite: options[:language]

          I18n.default_locale = language.language_code
        end

        def add_frontend_components
          @external_assets = []

          @external_assets << Middleman::Presentation::FrontendComponent.new(name: 'jquery', version: '~1.11', javascripts: %w(dist/jquery))
          @external_assets << Middleman::Presentation::FrontendComponent.new(name: 'reveal.js', version: 'latest', javascripts: %w(lib/js/head.min js/reveal.min))
          @external_assets << Middleman::Presentation::FrontendComponent.new(name: 'lightbox2', github: 'dg-vrnetze/revealjs-lightbox2', javascripts: %w(js/lightbox))
          @external_assets << Middleman::Presentation::FrontendComponent.new(
            name: 'middleman-presentation-theme-common',
            github: 'dg-vrnetze/middleman-presentation-theme-common',
            stylesheets: %w(stylesheets/middleman-presentation-theme-common),
            javascripts: %w(javascripts/middleman-presentation-theme-common)
          )

          @external_assets.concat Middleman::Presentation::FrontendComponent.parse(Middleman::Presentation.config.components)
        end

        def add_theme
          if Middleman::Presentation.config.theme.blank?
            @external_assets << Middleman::Presentation::FrontendComponent.new(
              name: 'middleman-presentation-theme-default',
              github: 'maxmeyer/middleman-presentation-theme-default',
              stylesheets: %w(stylesheets/middleman-presentation-theme-default)
            )
          else
            @external_assets.concat Middleman::Presentation::FrontendComponent.parse(Middleman::Presentation.config.theme)
          end
        end

        def set_variables_for_templates
          @bower_directory = options[:bower_directory]
          @author          = options[:author]
          @speaker         = options[:speaker]
          @title           = options[:title]
          @description     = options[:description]
          @subtitle        = options[:subtitle]
          @date            = options[:date]
          @homepage        = options[:homepage]
          @company         = options[:company]
          @license         = options[:license]
          @location        = options[:location]
          @audience        = options[:audience]

          @email_address   = options[:email_address]
          @phone_number    = options[:phone_number]
          @github_url      = options[:github_url]

          @version         = options[:version]
          @project_id      = format '%s-%s', ActiveSupport::Inflector.transliterate(options[:title]).parameterize, SecureRandom.hex
        end

        def set_configuration_for_revealjs
          @revealjs_config = {}
          @revealjs_config[:controls]                 = options[:activate_controls]
          @revealjs_config[:progress]                 = options[:activate_progress]
          @revealjs_config[:history]                  = options[:activate_history]
          @revealjs_config[:center]                   = options[:activate_center]
          @revealjs_config[:slide_number]             = options[:activate_slide_number]
          @revealjs_config[:default_transition_type]  = options[:default_transition_type]
          @revealjs_config[:default_transition_speed] = options[:default_transition_speed]
        end

        def create_middleman_data_files
          template 'data/metadata.yml.tt', File.join(data_directory, 'metadata.yml')
          template 'data/config.yml.tt', File.join(data_directory, 'config.yml')
        end

        def create_bower_configuration_files
          template '.bowerrc.tt', File.join(root_directory, '.bowerrc')
          template 'bower.json.tt', File.join(root_directory, 'bower.json')
        end

        def create_rake_file
          template 'Rakefile', File.join(root_directory, 'Rakefile')
        end

        def create_slides_ignore_file
          create_file File.join(root_directory, '.slidesignore'), "# empty\n"
        end

        def add_gems_to_gem_file
          if ENV['MM_ENV'] == 'development'
            append_to_file File.join(root_directory, 'Gemfile'), <<-EOS.strip_heredoc

            gem 'middleman-presentation', path: '#{File.expand_path('../../../../', __FILE__)}

            EOS
          else
            append_to_file File.join(root_directory, 'Gemfile'), <<-EOS.strip_heredoc

            gem 'middleman-presentation'

            EOS
          end

          append_to_file File.join(root_directory, 'Gemfile'), <<-EOS.strip_heredoc

          group :development, :test do
            gem 'pry'
            gem 'byebug'
            gem 'pry-byebug'
          end

          gem 'kramdown'
          gem 'github-markup'
          gem 'liquid'
          gem 'rake'
          EOS
        end

        def add_configuration_for_middleman_presentation
          append_to_file File.join(root_directory, 'config.rb'), <<-EOS.strip_heredoc

          activate :presentation

          set :markdown_engine, :kramdown
          set :markdown, parse_block_html: true

          bower_directory = '#{@bower_directory}'

          if respond_to?(:sprockets) && sprockets.respond_to?(:import_asset)
            sprockets.append_path File.join(root, bower_directory)

            patterns = [
              '.png',  '.gif', '.jpg', '.jpeg', '.svg', # Images
              '.eot',  '.otf', '.svc', '.woff', '.ttf', # Fonts
              '.js',                                    # Javascript
            ].map { |e| File.join(bower_directory, '**', "*\#{e}") }

            require 'rake/file_list'

            list = Rake::FileList.new(*patterns) do |l|
              l.exclude(/src/)
              l.exclude(/test/)
              l.exclude(/demo/)
              l.exclude { |f| !File.file? f }
            end

            list.each do |f|
              sprockets.import_asset Pathname.new(f).relative_path_from(Pathname.new(bower_directory))
            end

            Rake::FileList.new(File.join('vendor/assets/components', '**', 'notes.html' )).each do |f|
              sprockets.import_asset(Pathname.new(f).relative_path_from(Pathname.new(bower_directory))) { |local_path| Pathname.new('javascripts') + local_path }
            end

            Rake::FileList.new(File.join('vendor/assets/components', '**', 'pdf.css' )).each do |f|
              sprockets.import_asset(Pathname.new(f).relative_path_from(Pathname.new(bower_directory))) { |local_path| Pathname.new('stylesheets') + local_path }
            end
          end
          EOS
        end

        def add_patterns_to_gitignore
          append_to_file File.join(root_directory, '.gitignore'), <<-EOS.strip_heredoc
          *.zip
          *.tar.gz
          tmp/
          EOS
        end

        def create_application_asset_files
          template 'source/stylesheets/application.scss.tt', File.join(middleman_source_directory, 'stylesheets', 'application.scss')
          template 'source/javascripts/application.js.tt', File.join(middleman_source_directory, 'javascripts', 'application.js')
        end

        def create_image_directory
          empty_directory File.join(middleman_source_directory, 'images')
        end

        def create_presentation_layout
          copy_file 'source/layout.erb', File.join(middleman_source_directory, 'layout.erb')
          copy_file 'source/index.html.erb', File.join(middleman_source_directory, 'index.html.erb')
        end

        def create_default_slides
          return unless options[:create_predefined_slides]

          PredefinedSlideTemplateDirectory.new(working_directory: root_directory).template_files.each do |file|
            template file, File.join(slides_directory, File.basename(file, '.tt'))
          end
        end

        def create_default_license_file_to_presentation
          copy_file 'LICENSE.presentation', File.join(root_directory, 'LICENSE.presentation')
        end

        def create_helper_scripts
          %w(start bootstrap slide presentation build).each do |s|
            copy_file File.join('script', s), File.join(root_directory, 'script', s)
            chmod File.join(root_directory, 'script', s), 0755
          end
        end

        def install_external_assets
          inside directory do
            message = format('`bower`-command cannot be found in PATH "%s". Please make sure it is installed and PATH includes the directory where is stored.', ENV['PATH'])
            fail Thor::Error, message if options[:check_for_bower] && File.which('bower').blank?

            result = run('bower update', capture: true) if options[:install_assets] == true
            fail Thor::Error, "Error executing `bower`-command. Please fix your setup and run again:\n#{result}" unless $CHILD_STATUS.exitstatus == 0
          end
        end

        def install_gems
          inside directory do
            Bundler.with_clean_env do
              result = run('bundle install', capture: true) if options[:install_assets] == true
              fail Thor::Error, "Error executing `bundle`-command. Please fix your setup and run again:\n#{result}" unless $CHILD_STATUS.exitstatus == 0
            end
          end
        end

        def initialize_git_directory
          return unless options[:initialize_git]

          inside directory do
            run 'git init'
            run 'git add -A .'
            run 'git commit -m Init'
          end
        end

        no_commands do
          attr_reader :root_directory

          def data_directory
            File.join root_directory, 'data'
          end

          def middleman_source_directory
            File.join root_directory, 'source'
          end

          def slides_directory
            File.join middleman_source_directory, Middleman::Presentation.config.slides_directory
          end
        end
      end
    end
  end
end