module Bosh::Director
  module Models
    class IpAddress < Sequel::Model(Bosh::Director::Config.db)
      include IpUtil

      many_to_one :instance
      many_to_one :vm
      many_to_one :orphaned_vm

      def validate
        raise 'No instance or orphaned VM associated with IP' if instance_id.nil? && orphaned_vm_id.nil?
        raise 'IP address cannot have both instance id and orphaned VM id' if !instance_id.nil? && !orphaned_vm_id.nil?
        validates_presence :instance_id, allow_nil: true
        validates_presence :orphaned_vm_id, allow_nil: true
        validates_presence :task_id
        validates_presence :address_str
        validates_unique :address_str
        raise 'Invalid type for address_str column' unless address_str.is_a?(String)
      end

      def before_create
        self.created_at ||= Time.now
      end

      def info
        [
          "#{instance.deployment.name}.#{instance.job}/#{instance.index}",
          network_name,
          "#{to_ipaddr(address_str)} (#{type})"
        ].join(' - ')
      end

      def formatted_ip
        address.to_s
      end

      def formatted_ip_without_prefix_for_single_ips
        if ( formatted_ip.include?(':') && formatted_ip.include?("/#{Bosh::Director::DeploymentPlan::Network::IPV6_DEFAULT_PREFIX_SIZE}") ) ||
          ( formatted_ip.include?('.')  && formatted_ip.include?("/#{Bosh::Director::DeploymentPlan::Network::IPV4_DEFAULT_PREFIX_SIZE}") )
          formatted_ip.split('/')[0]
        else
          formatted_ip
        end
      end

      def type
        static ? 'static' : 'dynamic'
      end

      def address
        unless address_str.include?('/') || address_str.match?(/\A\d+\z/)
          info_display = ''
          begin
            info_display = info
          rescue StandardError
            info_display = 'missing_info'
          end
          raise "Unexpected address '#{address_str}' (#{info_display})"
        end

        to_ipaddr(address_str)
      end

      def to_s
        info
      end
    end
  end
end
