/**
 * Modern JavaScript Message Factory for JamKazam WebSocket Communication
 * Based on the legacy AAB_message_factory.js, updated for ES6+ and React compatibility
 */

// Message types for WebSocket communication
export const MessageType = {
  LOGIN: "LOGIN",
  LOGIN_ACK: "LOGIN_ACK",
  LOGIN_MUSIC_SESSION: "LOGIN_MUSIC_SESSION",
  LOGIN_MUSIC_SESSION_ACK: "LOGIN_MUSIC_SESSION_ACK",
  LEAVE_MUSIC_SESSION: "LEAVE_MUSIC_SESSION",
  LEAVE_MUSIC_SESSION_ACK: "LEAVE_MUSIC_SESSION_ACK",
  HEARTBEAT: "HEARTBEAT",
  HEARTBEAT_ACK: "HEARTBEAT_ACK",
  SUBSCRIBE: "SUBSCRIBE",
  UNSUBSCRIBE: "UNSUBSCRIBE",
  SUBSCRIPTION_MESSAGE: "SUBSCRIPTION_MESSAGE",
  SUBSCRIBE_BULK: "SUBSCRIBE_BULK",
  USER_STATUS: "USER_STATUS",

  // Friend notifications
  FRIEND_UPDATE: "FRIEND_UPDATE",
  FRIEND_REQUEST: "FRIEND_REQUEST",
  FRIEND_REQUEST_ACCEPTED: "FRIEND_REQUEST_ACCEPTED",
  FRIEND_SESSION_JOIN: "FRIEND_SESSION_JOIN",
  NEW_USER_FOLLOWER: "NEW_USER_FOLLOWER",
  NEW_BAND_FOLLOWER: "NEW_BAND_FOLLOWER",

  // Session notifications
  SESSION_INVITATION: "SESSION_INVITATION",
  SESSION_ENDED: "SESSION_ENDED",
  JOIN_REQUEST: "JOIN_REQUEST",
  JOIN_REQUEST_APPROVED: "JOIN_REQUEST_APPROVED",
  JOIN_REQUEST_REJECTED: "JOIN_REQUEST_REJECTED",
  SESSION_JOIN: "SESSION_JOIN",
  SESSION_DEPART: "SESSION_DEPART",
  TRACKS_CHANGED: "TRACKS_CHANGED",
  MUSICIAN_SESSION_JOIN: "MUSICIAN_SESSION_JOIN",
  BAND_SESSION_JOIN: "BAND_SESSION_JOIN",
  SCHEDULED_SESSION_INVITATION: "SCHEDULED_SESSION_INVITATION",
  SCHEDULED_SESSION_RSVP: "SCHEDULED_SESSION_RSVP",
  SCHEDULED_SESSION_RSVP_APPROVED: "SCHEDULED_SESSION_RSVP_APPROVED",
  SCHEDULED_SESSION_RSVP_CANCELLED: "SCHEDULED_SESSION_RSVP_CANCELLED",
  SCHEDULED_SESSION_RSVP_CANCELLED_ORG: "SCHEDULED_SESSION_RSVP_CANCELLED_ORG",
  SCHEDULED_SESSION_CANCELLED: "SCHEDULED_SESSION_CANCELLED",
  SCHEDULED_SESSION_RESCHEDULED: "SCHEDULED_SESSION_RESCHEDULED",
  SCHEDULED_SESSION_REMINDER: "SCHEDULED_SESSION_REMINDER",
  SCHEDULED_SESSION_COMMENT: "SCHEDULED_SESSION_COMMENT",

  SCHEDULED_JAMCLASS_INVITATION: "SCHEDULED_JAMCLASS_INVITATION",
  LESSON_MESSAGE: "LESSON_MESSAGE",

  // Recording notifications
  MUSICIAN_RECORDING_SAVED: "MUSICIAN_RECORDING_SAVED",
  BAND_RECORDING_SAVED: "BAND_RECORDING_SAVED",
  RECORDING_STARTED: "RECORDING_STARTED",
  RECORDING_ENDED: "RECORDING_ENDED",
  RECORDING_MASTER_MIX_COMPLETE: "RECORDING_MASTER_MIX_COMPLETE",
  DOWNLOAD_AVAILABLE: "DOWNLOAD_AVAILABLE",
  RECORDING_STREAM_MIX_COMPLETE: "RECORDING_STREAM_MIX_COMPLETE",

  // Band notifications
  BAND_INVITATION: "BAND_INVITATION",
  BAND_INVITATION_ACCEPTED: "BAND_INVITATION_ACCEPTED",

  // Text message
  TEXT_MESSAGE: "TEXT_MESSAGE",
  CHAT_MESSAGE: "CHAT_MESSAGE",
  SEND_CHAT_MESSAGE: "SEND_CHAT_MESSAGE",

  // Broadcast notifications
  SOURCE_UP_REQUESTED: "SOURCE_UP_REQUESTED",
  SOURCE_DOWN_REQUESTED: "SOURCE_DOWN_REQUESTED",
  SOURCE_UP: "SOURCE_UP",
  SOURCE_DOWN: "SOURCE_DOWN",

  TEST_SESSION_MESSAGE: "TEST_SESSION_MESSAGE",
  PING_REQUEST: "PING_REQUEST",
  PING_ACK: "PING_ACK",
  PEER_MESSAGE: "PEER_MESSAGE",
  CLIENT_UPDATE: "CLIENT_UPDATE",
  GENERIC_MESSAGE: "GENERIC_MESSAGE",
  RELOAD: "RELOAD",
  RESTART_APPLICATION: "RESTART_APPLICATION",
  STOP_APPLICATION: "STOP_APPLICATION",
  SERVER_BAD_STATE_RECOVERED: "SERVER_BAD_STATE_RECOVERED",
  SERVER_GENERIC_ERROR: "SERVER_GENERIC_ERROR",
  SERVER_REJECTION_ERROR: "SERVER_REJECTION_ERROR",
  SERVER_BAD_STATE_ERROR: "SERVER_BAD_STATE_ERROR",
  SERVER_DUPLICATE_CLIENT_ERROR: "SERVER_DUPLICATE_CLIENT_ERROR"
};

// Route prefixes for message routing
export const RouteToPrefix = {
  CLIENT: "client",
  SESSION: "session",
  SERVER: "server",
  USER: "user"
};

// Utility function to get a simple cookie value (replacement for $.cookie)
const getCookie = (name) => {
  const value = `; ${document.cookie}`;
  const parts = value.split(`; ${name}=`);
  if (parts.length === 2) return parts.pop().split(';').shift();
  return null;
};

// Helper function to create client container
const createClientContainer = (type, target, inner) => {
  const typeField = type.toLowerCase();
  return {
    type,
    route_to: target,
    [typeField]: inner
  };
};

// Helper function to create route to client
const routeToClient = (clientId) => `${RouteToPrefix.CLIENT}:${clientId}`;

// Helper function to create route to session
const routeToSession = (sessionId) => `${RouteToPrefix.SESSION}:${sessionId}`;

// Message Factory class
class MessageFactory {
  // Ping the provided client_id
  ping(clientId) {
    const data = {};
    return createClientContainer(MessageType.PING_REQUEST, routeToClient(clientId), data);
  }

  // Heartbeat message
  heartbeat(lastNotificationSeen, lastNotificationSeenAt, active) {
    const data = {
      notification_seen: lastNotificationSeen,
      notification_seen_at: lastNotificationSeenAt,
      active
    };
    return createClientContainer(MessageType.HEARTBEAT, RouteToPrefix.SERVER, data);
  }

  // User Status update message
  userStatus(active, status) {
    const data = { active, status };
    return createClientContainer(MessageType.USER_STATUS, RouteToPrefix.SERVER, data);
  }

  // Chat message (fixed implementation from original)
  chatMessage(channel, message) {
    const data = { channel, msg: message };
    return createClientContainer(MessageType.SEND_CHAT_MESSAGE, RouteToPrefix.SERVER, data);
  }

  // Create a login message using user/pass
  loginWithUserPass(username, password) {
    const login = { username, password };
    return createClientContainer(MessageType.LOGIN, RouteToPrefix.SERVER, login);
  }

  // Create a login message using token
  // reconnect_music_session_id is optional
  loginWithToken(token, clientId, reconnectMusicSessionId, clientType) {
    const login = {
      token,
      client_id: clientId,
      client_type: clientType
    };
    if (reconnectMusicSessionId) {
      login.reconnect_music_session_id = reconnectMusicSessionId;
    }
    return createClientContainer(MessageType.LOGIN, RouteToPrefix.SERVER, login);
  }

  // Logout message
  logout() {
    const logout = {};
    return createClientContainer("LOGOUT", RouteToPrefix.SERVER, logout);
  }

  // Create a login message using only the client_id (for latency_tester)
  loginWithClientId(clientId, clientType) {
    if (clientType !== 'latency_tester') {
      throw new Error("client_type must be latency_tester in loginWithClientId");
    }
    const login = { client_id: clientId, client_type: clientType };
    return createClientContainer(MessageType.LOGIN, RouteToPrefix.SERVER, login);
  }

  // Create a music session login message
  loginMusicSession(musicSession) {
    const loginMusicSession = { music_session: musicSession };
    return createClientContainer(MessageType.LOGIN_MUSIC_SESSION, RouteToPrefix.SERVER, loginMusicSession);
  }

  // Client-to-client message
  clientP2PMessage(senderClientId, receiverClientId, message) {
    const peerMessage = { message };
    const result = createClientContainer(MessageType.PEER_MESSAGE, routeToClient(receiverClientId), peerMessage);
    result.from = senderClientId;
    return result;
  }

  // Subscribe to notifications
  subscribe(type, id) {
    const subscribeMsg = { type, id };
    return createClientContainer(MessageType.SUBSCRIBE, RouteToPrefix.SERVER, subscribeMsg);
  }

  // Subscribe to multiple types/ids
  subscribeBulk(types, ids) {
    const subscribeBulkMsg = { types, ids };
    return createClientContainer(MessageType.SUBSCRIBE_BULK, RouteToPrefix.SERVER, subscribeBulkMsg);
  }

  // Unsubscribe from notifications
  unsubscribe(type, id) {
    const unsubscribeMsg = { type, id };
    return createClientContainer(MessageType.UNSUBSCRIBE, RouteToPrefix.SERVER, unsubscribeMsg);
  }
}

// Export a singleton instance for easy use
export const messageFactory = new MessageFactory();

// Also export the class for custom instantiation if needed
export default MessageFactory;
