class InstanceController < ApplicationController
  def create
    zone = create_instance_params
    public_id = Nanoid.generate(size: 6)
    name = Spicy::Proton.pair(" ")
    password = Nanoid.generate(size: 4, alphabet: "0123456789")
    instance = Instance.new(zone: zone, public_id: public_id, name: name, password: password)
    if instance.save
      @id = instance.public_id
      @password = instance.password
      render "set_password"
    end
  end

  def create_from_fe
    info = create_from_fe_params
    # Make sure we have the correct string
    if info.start_with?("NMs on cooldown:")
      str = info.sub("NMs on cooldown:", "").strip
      split = str.split(" → ")
      ts = Time.now.utc
      zone = nil
      results = split.map do |s|
        # Grab the name and time until it can be repopped
        name, time = s.split("(")
        name = name.strip
        time = time.gsub(/\D/, "") # remove anything but digits

        # Try and guess the zone based on names
        if zone.nil?
          if APP_DATA[:anemos][:nms].any? { |nm| nm[:nick] == name }
            zone = "anemos"
          elsif APP_DATA[:pagos][:nms].any? { |nm| nm[:nick] == name }
            zone = "pagos"
          elsif APP_DATA[:pyros][:nms].any? { |nm| nm[:nick] == name }
            zone = "pyros"
          elsif APP_DATA[:hydatos][:nms].any? { |nm| nm[:nick] == name }
            zone = "hydatos"
          end
        end

        {
          name: APP_DATA[zone.to_sym][:nms].find { |nm| nm[:nick] == name }[:name].parameterize,
          created_at: ts - (120.minutes - time.to_i.minutes)
        }
      end

      public_id = Nanoid.generate(size: 6)
      name = Spicy::Proton.pair(" ")
      password = Nanoid.generate(size: 4, alphabet: "0123456789")
      instance = Instance.new(zone: zone, public_id: public_id, name: name, password: password)
      if instance.save
        Pop.insert_all(results.map { |r| { instance_id: instance.id, **r } })
        @id = instance.public_id
        @password = instance.password
        render "set_password"
      end
    end
  end

  def clone
    instance = clone_instance_params
    i = Instance.find_by(public_id: instance)
    new_inst = i.deep_clone(include: [ :fairies, :pops ])
    new_inst.public_id = Nanoid.generate(size: 6)
    new_inst.password = Nanoid.generate(size: 4, alphabet: "0123456789")
    new_inst.name = Spicy::Proton.pair(" ")
    if new_inst.save
      @id = new_inst.public_id
      @password = new_inst.password
      render "set_password"
    end
  end

  def show
    @instance = Instance.includes(:pops, :fairies).find_by(public_id: show_instance_params)
    if @instance
      @forecast = Weather.forecast(@instance.zone.to_sym)
    else
      redirect_to root_path
    end
  end

  def pop
    instance_id, nm, pwd = pop_instance_params
    parent_instance = Instance.find_by(public_id: instance_id)
    # Check if the same NM is already popped. Helps prevent potential desync race conditions.
    potential_pop = Pop.find_by(instance_id: parent_instance.id, name: nm, created_at: 120.minutes.ago..Time.now)
    if parent_instance.password == pwd and potential_pop.nil?
      pop = Pop.new(instance_id: parent_instance.id, name: nm)
      if pop.save
        @instance = Instance.includes(:pops, :fairies).find_by(public_id: instance_id)
        @forecast = Weather.forecast(@instance.zone.to_sym)
        render partial: "list", locals: { instance: @instance, forecast: @forecast }
      end
    end
  end

  def adjust_pop
    instance_id, nm, pwd = pop_instance_params
    parent_instance = Instance.find_by(public_id: instance_id)
    if params[:mins] && params[:mins].to_i < 120 && params[:pwd] == parent_instance.password
      ts = Time.now.utc
      pop = Pop.find_by(instance_id: parent_instance.id, name: nm, created_at: 120.minutes.ago..Time.now)
      pop.created_at = Time.at(ts - params[:mins].to_i.minutes).utc
      pop.save
      @instance = Instance.includes(:pops, :fairies).find_by(public_id: instance_id)
      @forecast = Weather.forecast(@instance.zone.to_sym)
      render partial: "list", locals: { instance: @instance, forecast: @forecast }
    end
  end

  def reset
    instance_id, nm, pwd = pop_instance_params
    parent_instance = Instance.find_by(public_id: instance_id)
    if parent_instance.password == pwd
      Pop.delete_by(instance_id: parent_instance.id, name: nm)
      @instance = Instance.includes(:pops, :fairies).find_by(public_id: instance_id)
      @forecast = Weather.forecast(@instance.zone.to_sym)
      render partial: "list", locals: { instance: @instance, forecast: @forecast }
    end
  end

  def authenticate
    password, instance = auth_params
    inst = Instance.find_by(public_id: instance)
    if password == inst.password
      @id = inst.public_id
      @password = inst.password
      render "set_password"
    end
  end

  private

  def create_instance_params
    params.expect(:zone)
  end

  def create_from_fe_params
    params.expect(:info)
  end

  def clone_instance_params
    params.expect(:instance)
  end

  def show_instance_params
    params.expect(:public_id)
  end

  def pop_instance_params
    params.expect(:instance, :nm, :pwd)
  end

  def auth_params
    params.expect(:password, :instance)
  end
end