import {
  RootState,
  statusInternalError,
  getCurrentChannelForChannelViewer,
  statusNotFound,
} from 'mweb/common/reducers/root';
import { Location } from 'mweb/common/reducers/app';
import {
  ChannelOnlineStatus,
  assertChannelOnlineStatus,
} from 'mweb/common/reducers/data/channels';

/**
 * Cache expiration values by page, in seconds.
 */
export enum PageExpiry {
  ChatEmbed = 1800,
  ChannelOnline = 600,
  ChannelOffline = 60,
  VOD = 1800,
  Error = 0,
  Default = 600,
  LTV_TO_VOD = 3600,
  LTV_TO_LIVE = 60,
  CHANNEL_OFFLINE_TO_PROFILE = 60,
  DEFAULT_REDIRECT = 60,
}

export const MAX_STALE_WHILE_REVALIDATE_IN_SECONDS = 30;

/**
 * Returns the cache control header for the current page in seconds.
 *
 * @param state
 */
export function getCacheControlHeader(state: RootState): string {
  return buildCacheControlHeader(getCacheExpiry(state));
}

export function buildCacheControlHeader(cacheExpiryTime: PageExpiry): string {
  const maxAge = Math.max(
    0,
    cacheExpiryTime - MAX_STALE_WHILE_REVALIDATE_IN_SECONDS,
  );
  const swrTime = Math.max(0, cacheExpiryTime - maxAge);

  return `public, max-age=${maxAge}, stale-while-revalidate=${swrTime}`;
}

/**
 * Returns the cache expiry for the current page in seconds.
 *
 * @param state
 */
function getCacheExpiry(state: RootState): number {
  if (statusInternalError(state)) {
    return PageExpiry.Error;
  }
  if (statusNotFound(state)) {
    return PageExpiry.Default;
  }
  switch (state.app.location) {
    case Location.Channel:
      return getCacheExpiryForChannelViewer(state);
    case Location.ChatEmbed:
      return PageExpiry.ChatEmbed;
    case Location.VOD:
      return PageExpiry.VOD;
    default:
      return PageExpiry.Default;
  }
}

/**
 * Returns the cache expiry for the channel viewer in seconds.
 *
 * @param state
 */
function getCacheExpiryForChannelViewer(state: RootState): number {
  const channelDetails = getCurrentChannelForChannelViewer(state);
  if (channelDetails === undefined) {
    return PageExpiry.ChannelOffline;
  }
  switch (channelDetails.onlineStatus) {
    case ChannelOnlineStatus.Online:
      return PageExpiry.ChannelOnline;
    case ChannelOnlineStatus.Offline:
      return PageExpiry.ChannelOffline;
    case ChannelOnlineStatus.Unknown:
      return PageExpiry.ChannelOffline;
    default:
      return assertChannelOnlineStatus(channelDetails.onlineStatus);
  }
}
