module JamRuby
  class Diagnostic < ActiveRecord::Base

    # occurs when the client does not see a heartbeat from the server in a while
    NO_HEARTBEAT_ACK = 'NO_HEARTBEAT_ACK'

    # occurs when the client sees the socket go down
    WEBSOCKET_CLOSED_REMOTELY = 'WEBSOCKET_CLOSED_REMOTELY'

    # occurs when the client makes the socket go down
    WEBSOCKET_CLOSED_LOCALLY = 'WEBSOCKET_CLOSED_LOCALLY'

    # occurs when the websocket-gateway has finally given up entirely on a connection with no heartbeats seen in a while
    EXPIRED_STALE_CONNECTION = 'EXPIRED_STALE_CONNECTION'

    # occurs when the websocket-gateway is trying to handle a heartbeat, but can't find any state for the user.
    # this implies a coding error
    MISSING_CLIENT_STATE = 'MISSING_CLIENT_STATE'

    # the underlying database connection is gone when the heartbeat comes in
    MISSING_CONNECTION = 'MISSING_CONNECTION'

    # websocket gateway did not recognize message. indicates out-of-date websocket-gateway
    UNKNOWN_MESSAGE_TYPE = 'UNKNOWN_MESSAGE_TYPE'

    # empty route_to in message; which is invalid.  indicates programming error
    MISSING_ROUTE_TO = 'MISSING_ROUTE_TO'

    # websocket gateway got a client with the same client_id as an already-connected client
    DUPLICATE_CLIENT = 'DUPLICATE_CLIENT'

    # info about how the test went
    NETWORK_TEST_RESULT = 'NETWORK_TEST_RESULT'

    # step 2 of the FTUE... could the user select their gear?
    GEAR_SELECTION = 'GEAR_SELECTION'

    DIAGNOSTIC_TYPES = [NO_HEARTBEAT_ACK, WEBSOCKET_CLOSED_REMOTELY, EXPIRED_STALE_CONNECTION,
                        MISSING_CLIENT_STATE, UNKNOWN_MESSAGE_TYPE, MISSING_ROUTE_TO,
                        DUPLICATE_CLIENT, WEBSOCKET_CLOSED_LOCALLY, NETWORK_TEST_RESULT, GEAR_SELECTION]

    # creator types #
    CLIENT = 'client'
    WEBSOCKET_GATEWAY = 'websocket-gateway'
    CREATORS = [CLIENT, WEBSOCKET_GATEWAY]

    self.primary_key = 'id'
    self.inheritance_column = 'nothing'

    belongs_to :user, :inverse_of => :diagnostics, :class_name => "JamRuby::User", :foreign_key => "user_id"

    validates :user, :presence => true
    validates :type, :inclusion => {:in => DIAGNOSTIC_TYPES}
    validates :creator, :inclusion => {:in => CREATORS}
    validates :data, length: {maximum: 100000}


    def self.expired_stale_connection(user, context)
      Diagnostic.save(EXPIRED_STALE_CONNECTION, user, WEBSOCKET_GATEWAY, context.to_json) if user
    end

    def self.missing_client_state(user, context)
      Diagnostic.save(MISSING_CLIENT_STATE, user, WEBSOCKET_GATEWAY, context.to_json) if user
    end

    def self.missing_connection(user, context)
      Diagnostic.save(MISSING_CONNECTION, user, WEBSOCKET_GATEWAY, context.to_json) if user
    end

    def self.duplicate_client(user, context)
      Diagnostic.save(DUPLICATE_CLIENT, user, WEBSOCKET_GATEWAY, context.to_json) if user
    end

    def self.unknown_message_type(user, client_msg)
      Diagnostic.save(UNKNOWN_MESSAGE_TYPE, user, WEBSOCKET_GATEWAY, client_msg.to_json) if user
    end

    def self.missing_route_to(user, client_msg)
      Diagnostic.save(MISSING_ROUTE_TO, user, WEBSOCKET_GATEWAY, client_msg.to_json) if user
    end


    def self.save(type, user, creator, data)
      diagnostic = Diagnostic.new
      if user.class == String
        diagnostic.user_id = user
      else
        diagnostic.user = user
      end

      diagnostic.data = data
      diagnostic.type = type
      diagnostic.creator = creator
      diagnostic.save
    end
  end

end
