# frozen_string_literal: true

require 'spec_helper'
require './lib/fusuma'
require './lib/fusuma/plugin/inputs/libinput_command_input'
require './lib/fusuma/plugin/filters/libinput_device_filter'

module Fusuma
  RSpec.describe Runner do
    describe '.run' do
      before do
        Singleton.__init__(MultiLogger)
        Singleton.__init__(Config)
        allow_any_instance_of(Runner).to receive(:run)
        allow_any_instance_of(LibinputCommand).to receive(:version)
          .and_return("1.8\n")
      end

      context 'when without option' do
        it 'should not enable debug mode' do
          expect(MultiLogger.instance).not_to be_debug_mode
          Runner.run
        end
      end

      context 'when run with argument "--version"' do
        # NOTE: skip print reload config message
        before { allow(MultiLogger).to receive(:info).with(anything) }
        it 'should print version' do
          expect(MultiLogger).to receive(:info)
            .with("Fusuma: #{Fusuma::VERSION}")
          expect(MultiLogger).to receive(:info)
            .with("libinput: #{LibinputCommand.new.version}")
          expect(MultiLogger).to receive(:info)
            .with("OS: #{`uname -rsv`}".strip)
          expect(MultiLogger).to receive(:info)
            .with("Distribution: #{`cat /etc/issue`}".strip)
          expect(MultiLogger).to receive(:info)
            .with("Desktop session: #{`echo $DESKTOP_SESSION $XDG_SESSION_TYPE`}".strip)
          expect { Runner.run(version: true) }.to raise_error(SystemExit)
        end
      end

      context 'when run with argument "-l"' do
        it 'should print device list' do
          allow(Device).to receive(:available) {
            [
              Device.new(name: 'test_device1'),
              Device.new(name: 'test_device2')
            ]
          }

          expected = <<~OUTPUT
            test_device1
            test_device2
          OUTPUT
          expect { Runner.run(list: true) }.to raise_error(SystemExit)
            .and output(/#{expected}/).to_stdout
        end
      end

      # TODO: remove from_option and command line options
      context 'when run with argument "--device="test_device2"' do
        it 'should set device' do
          allow(Device).to receive(:names) { %w[test_device1 test_device2] }
          expect(Plugin::Filters::LibinputDeviceFilter::KeepDevice)
            .to receive(:from_option=).with('test_device2')
          Runner.run(device: 'test_device2')
        end
      end

      context 'when run with argument "-v"' do
        it 'should enable debug mode' do
          MultiLogger.send(:new)
          Runner.run(verbose: true)
          expect(MultiLogger.instance).to be_debug_mode
        end
      end

      context 'when run with argument "-c path/to/config.yml"' do
        before do
          allow_any_instance_of(Runner).to receive(:run)
          @config = Config.instance

          string = <<~CONFIG
            swipe:
              3:
                left:
                  command: echo 'swipe left'

          CONFIG
          @file_path = Tempfile.open do |temp_file|
            temp_file.tap { |f| f.write(string) }
          end
        end
        it 'should assign custom_path' do
          expect { Runner.run(config_path: @file_path) }
            .to change { @config.custom_path }.from(nil).to(@file_path)
        end
      end
    end
  end
end
