# frozen_string_literal: true

module Sass
  class Compiler
    # The {Channel} class.
    #
    # It manages the lifecycle of {Dispatcher}.
    class Channel
      def initialize(*args, **kwargs, &block)
        @args = args
        @kwargs = kwargs
        @block = block
        @dispatcher = Dispatcher.new(*@args, **@kwargs, &@block)
        @mutex = Mutex.new
      end

      def close
        @mutex.synchronize do
          unless @dispatcher.nil?
            @dispatcher.close
            @dispatcher = nil
          end
        end
      end

      def closed?
        @mutex.synchronize do
          @dispatcher.nil?
        end
      end

      def stream(session)
        @mutex.synchronize do
          raise IOError, 'closed compiler' if @dispatcher.nil?

          Stream.new(@dispatcher, session)
        rescue Errno::EBUSY
          @dispatcher = Dispatcher.new(*@args, **@kwargs, &@block)
          Stream.new(@dispatcher, session)
        end
      end

      # The {Stream} between {Dispatcher} and {Session}.
      class Stream
        attr_reader :id

        def initialize(dispatcher, session)
          @dispatcher = dispatcher
          @id = @dispatcher.subscribe(session)
        end

        def close
          @dispatcher.unsubscribe(@id)
        end

        def error(...)
          @dispatcher.error(...)
        end

        def send_proto(...)
          @dispatcher.send_proto(...)
        end
      end

      private_constant :Stream
    end

    private_constant :Channel
  end
end
