"use strict";

//
// Copyright © 2024 MediaMall Technologies, Inc.  All rights reserved.
//

import { NativeModules, Platform, NativeEventEmitter } from 'react-native';

/**
 * @ignore
 */
const LINKING_ERROR = `The package 'react-native-younify-connect-sdk' doesn't seem to be linked. Make sure: \n\n` + Platform.select({
  ios: "- You have run 'pod install'\n",
  default: ''
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';

/**
 * @ignore
 */
const YounifyConnectSDK = NativeModules.YounifyConnectSDK ? NativeModules.YounifyConnectSDK : new Proxy({}, {
  get() {
    throw new Error(LINKING_ERROR);
  }
});
const connectEvt = new NativeEventEmitter(YounifyConnectSDK);

/** Error codes reported by the SDK. */
export let ErrorCode = /*#__PURE__*/function (ErrorCode) {
  /** An unknown error occurred. */
  ErrorCode["Unknown"] = "-10000";
  /** The current version of the SDK is no longer supported. */
  ErrorCode["SDKVersionNotSupported"] = "-10001";
  /** The system is currently down for maintenance. */
  ErrorCode["SystemMaintenance"] = "-10002";
  /** A network error occurred. The user is either offline or the server returned an invalid response. The specific http status code is available in the statusCode property of the userInfo dictionary. */
  ErrorCode["NetworkRequestFailed"] = "-10003";
  /** The requested operation has been canceled. */
  ErrorCode["OperationCanceled"] = "-10004";
  /** An invalid argument was encountered. */
  ErrorCode["InvalidArgument"] = "-10005";
  /** The service fetch operation failed. */
  ErrorCode["ServiceFetchingFailed"] = "-20000";
  /** The service linking operation failed. */
  ErrorCode["ServiceLinkingFailed"] = "-20001";
  /** The service is not supported by the SDK. */
  ErrorCode["ServiceUnsupported"] = "-20002";
  /** The service is temporarily unavailable. */
  ErrorCode["ServiceTemporarilyUnavailable"] = "-20003";
  /** The service login failed. The user should verify their login information. */
  ErrorCode["ServiceLoginFailed"] = "-20004";
  /** The service profile was not found. The user should select another profile. */
  ErrorCode["ServiceProfileNotFound"] = "-20005";
  /** The service profile pin was not correct. The user should enter their pin again. */
  ErrorCode["ServiceProfilePinMismatch"] = "-20006";
  /** This service content may no longer be available. */
  ErrorCode["ServiceContentNotFound"] = "-20007";
  /** The view context is invalid. */
  ErrorCode["InvalidViewContext"] = "-30000";
  /** The user tried to perform an action that requires privacy policy consent. */
  ErrorCode["UserConsentRequired"] = "-40000";
  return ErrorCode;
}({});
;

/**
 * Contains partial response data for an operation that was promise rejected.
 *
 * Some operations can return valid, partial data despite having errors occur that an application may which to treat as non-fatal.
 */

/**
 * Contains extra information for {@link ErrorCode.NetworkRequestFailed} errors.
 */

/**
 * Contains extra information for {@link ErrorCode.InvalidArgument} errors.
 */

/**
 * Contains extra information for {@link ErrorCode.ServiceLinkingFailed} errors.
 */

/** Error object. */

/**
 * Log level.
 */
export let LogLevel = /*#__PURE__*/function (LogLevel) {
  /** Trace. */
  LogLevel[LogLevel["Trace"] = 0] = "Trace";
  /** Debug. */
  LogLevel[LogLevel["Debug"] = 1] = "Debug";
  /** Information */
  LogLevel[LogLevel["Information"] = 2] = "Information";
  /** Warning */
  LogLevel[LogLevel["Warning"] = 3] = "Warning";
  /** Error */
  LogLevel[LogLevel["Error"] = 4] = "Error";
  /** Critical */
  LogLevel[LogLevel["Critical"] = 5] = "Critical";
  /** None */
  LogLevel[LogLevel["None"] = 6] = "None";
  return LogLevel;
}({});

/**
 * Log listener.
 */

/**
 * Token handler.
 *
 * Implement this handler to receive token events from the sdk and to handle backend token renewals. The instance can be set in {@link ConnectOptions}.
*/

/**
 * A Cancellation ticket.
 *
 * A special ticket that allows coordination of cancellation operations between a requestor and worker.
 *
 */
export class CancellationTicket {
  static _nextId = 1;
  static _none = new CancellationTicket();
  static get none() {
    return CancellationTicket._none;
  }
  constructor() {
    this.id = (CancellationTicket._nextId++).toString() + '-' + Date.now().toString(36);
    this.canceled = false;
  }

  /**
   * Whether a cancellation has been requested.
   */
  get isCancellationRequested() {
    return this.canceled;
  }

  /**
   * @throws {@link Error} if {@link isCancellationRequested} is set.
   */
  throwIfCancellationRequested() {
    if (this.isCancellationRequested) throw {
      code: ErrorCode.OperationCanceled,
      message: 'The requested operation has been canceled.',
      userInfo: null
    };
  }

  /**
   * Requests that the coordinated operation be canceled and causes {@link isCancellationRequested} to be set.
   *
   * @returns A promise that resolves to a bool indicating whether the cancel was successful.
   */
  async cancel() {
    if (this === CancellationTicket._none) return;
    this.canceled = true;
    return await YounifyConnectSDK.cancel(this.id);
  }
}

/**
 * Younify Connect SDK startup options.
 *
 * Set the properties of this object to configure the sdk.
 * The {@link key} and {@link tokenHandler} properties are required.
 * The {@link accessToken} and {@link refreshToken} properties are required for linking and fetching service content for the user and can be set at a later time if unknown at startup. The tokens can be created from the backend api.
 * The {@link tokenHandler} must be set to handle updated tokens and requests from the sdk to renew tokens from the backend api.
 */

/**
 * Streaming service link.
 *
 * Contains informative user properties about the linked streaming service.
 */

class StreamingServiceLinkFactory {
  static createFromJsonObj(obj) {
    return obj;
  }
}

/**
 * Streaming service.
 *
 * Represents a streaming service.
 */

class StreamingServiceFactory {
  static StreamingServiceEquals = function (obj) {
    return this.name == obj.name;
  };
  static createFromJsonObj(obj) {
    let service = obj;
    service.equals = StreamingServiceFactory.StreamingServiceEquals;
    service.link = StreamingServiceLinkFactory.createFromJsonObj(service.link);
    return service;
  }
  static createFromJsonArray(obj) {
    return obj.map(x => StreamingServiceFactory.createFromJsonObj(x));
  }
}

/**
 * Streaming service content type.
 *
 * The type of content the {@link StreamingContent} object represents.
 */
export let StreamingContentType = /*#__PURE__*/function (StreamingContentType) {
  /** Invalid type */
  StreamingContentType[StreamingContentType["Invalid"] = -1] = "Invalid";
  /** Folder */
  StreamingContentType[StreamingContentType["Folder"] = 0] = "Folder";
  /** Video */
  StreamingContentType[StreamingContentType["Video"] = 1] = "Video";
  return StreamingContentType;
}({});

/**
 * Streaming service content.
 *
 * Represents a content item from a streaming service.
 */

class StreamingContentFactory {
  static createFromJsonObj(obj) {
    return obj;
  }
  static createFromJsonArray(obj) {
    return obj.map(x => StreamingContentFactory.createFromJsonObj(x));
  }
}

/**
 * Streaming service content details.
 *
 * Holds additional content item details for a {@link StreamingContent} object.
 */

class StreamingContentDetailsFactory {
  static createFromJsonObj(obj) {
    return obj;
  }
}

/**
 * Streaming service content category.
 *
 * Represents a streaming service category for a user.
 */

class StreamingCategoryImpl {
  constructor(nameOrCategory) {
    if (typeof nameOrCategory === 'string') this.name = nameOrCategory;else this.name = nameOrCategory.name;
  }
  equals(obj) {
    return this.name == obj.name;
  }
}
class StreamingCategoryFactory {
  static createFromJsonObj(obj) {
    return new StreamingCategoryImpl(obj);
  }
  static createFromJsonArray(obj) {
    return obj.map(x => StreamingCategoryFactory.createFromJsonObj(x));
  }
}

/**
 * Well-known streaming service content categories.
 *
 * Holds a list of well-known streaming service categories.
*/
export let StreamingCategories;
(function (_StreamingCategories) {
  const YourWatchlist = _StreamingCategories.YourWatchlist = new StreamingCategoryImpl("Your Watchlist");
  const ContinueWatching = _StreamingCategories.ContinueWatching = new StreamingCategoryImpl("Continue Watching");
  const RecommendedForYou = _StreamingCategories.RecommendedForYou = new StreamingCategoryImpl("Recommended for You");
  const TrendingAndPopular = _StreamingCategories.TrendingAndPopular = new StreamingCategoryImpl("Trending & Popular");
  const CriticallyAcclaimed = _StreamingCategories.CriticallyAcclaimed = new StreamingCategoryImpl("Critically Acclaimed");
})(StreamingCategories || (StreamingCategories = {}));
/**
 * Fetch content category service result.
 *
 * Holds the results of a fetch content request for a given streaming service.
 */
class FetchContentCategoryServiceResultFactory {
  static createFromJsonObj(obj) {
    let res = obj;
    res.service = StreamingServiceFactory.createFromJsonObj(res.service);
    res.content = StreamingContentFactory.createFromJsonArray(res.content);
    return res;
  }
  static createFromJsonArray(obj) {
    return obj.map(x => FetchContentCategoryServiceResultFactory.createFromJsonObj(x));
  }
}

/**
 * Fetch content category result.
 *
 * Holds the results of a fetch content request for a category and each streaming service
 */

class FetchContentCategoryResultFactory {
  static createFromJsonObj(obj) {
    let res = obj;
    res.category = StreamingCategoryFactory.createFromJsonObj(res.category);
    res.services = FetchContentCategoryServiceResultFactory.createFromJsonArray(res.services);
    return res;
  }
  static createFromJsonArray(obj) {
    return obj.map(x => FetchContentCategoryResultFactory.createFromJsonObj(x));
  }
}
class LinkServiceResultFactory {
  static createFromJsonObj(obj) {
    let res = obj;
    res.service = StreamingServiceFactory.createFromJsonObj(res.service);
    return res;
  }
}

/**
 * Search content service result.
 *
 * Holds the results of a search content request for a given streaming service.
 */

class SearchContentServiceResultFactory {
  static createFromJsonObj(obj) {
    let res = obj;
    res.service = StreamingServiceFactory.createFromJsonObj(res.service);
    res.content = StreamingContentFactory.createFromJsonArray(res.content);
    return res;
  }
  static createFromJsonArray(obj) {
    return obj.map(x => SearchContentServiceResultFactory.createFromJsonObj(x));
  }
}
class EventCategoryServiceErrorFactory {
  static createFromJsonObj(obj) {
    let res = obj;
    res.service = StreamingServiceFactory.createFromJsonObj(res.service);
    return res;
  }
}
class EventCategoryServiceCompleteFactory {
  static createFromJsonObj(obj) {
    let res = obj;
    res.category = StreamingCategoryFactory.createFromJsonObj(res.category);
    res.service = StreamingServiceFactory.createFromJsonObj(res.service);
    res.content = StreamingContentFactory.createFromJsonArray(res.content);
    return res;
  }
}
class EventSearchContentServiceCompleteFactory {
  static createFromJsonObj(obj) {
    let res = obj;
    res.service = StreamingServiceFactory.createFromJsonObj(res.service);
    res.content = StreamingContentFactory.createFromJsonArray(res.content);
    return res;
  }
}

/**
 * Younify Connect SDK main interface.
 *
 * Caution: When invoking a method, the sdk uses a limited task based processing architecture that may delay the execution of new operations until previous ones complete.
 * Special care should be taken when performing sdk operations in the background while allowing the user to interact in the foreground. Long running background operations
 * could negatively impact the responsiveness of your app. If you choose to use background operations, consider making them as short as possible or cancel them when users
 * interact in the foreground.
 */

/**
 * Younify Connect SDK main object.
 *
 * Use the {@link shared} singleton instance to interact with the sdk. Before the sdk can be meaningfully used {@link configure} must be called.
 */
export class Connect {
  static get shared() {
    if (!Connect.instance) Connect.instance = new Connect();
    return Connect.instance;
  }
  _logListener = null;
  _logListenerSubscriptions = new Array();
  _tokenHandler = null;
  _tokenHandlerSubscriptions = new Array();
  _nextRequestId = 0;
  constructor() {}
  async callBridge(f, h) {
    try {
      let res = await f();
      let hres = h(res);
      return hres;
    } catch (e) {
      let userInfo = e?.userInfo;
      let res = userInfo?.partialResult;
      if (res) {
        let pres = h(res);
        userInfo.partialResult = pres;
      }
      throw e;
    }
  }
  updateService(target, source) {
    if (target && source) Object.assign(target, source);
  }
  checkCancellationTicketAndGetId(cancellationTicket) {
    cancellationTicket = cancellationTicket || CancellationTicket.none;
    cancellationTicket.throwIfCancellationRequested();
    return cancellationTicket.id;
  }
  configure(options) {
    const logListener = options.logListener;
    if (this._logListener != logListener) {
      while (this._logListenerSubscriptions.length > 0) this._logListenerSubscriptions.pop()?.remove();
      this._logListener = logListener ?? null;
      if (logListener) this._logListenerSubscriptions.push(connectEvt.addListener("Log_onLog", evt => {
        logListener.onMessage(evt.level, evt.message);
      }));
    }
    const tokenHandler = options.tokenHandler;
    if (this._tokenHandler != tokenHandler) {
      while (this._tokenHandlerSubscriptions.length > 0) this._tokenHandlerSubscriptions.pop()?.remove();
      this._tokenHandler = tokenHandler ?? null;
      if (tokenHandler) {
        this._tokenHandlerSubscriptions.push(connectEvt.addListener("Token_onRenewTokens", evt => {
          const renewalId = evt.renewalId;
          const renewed = (newAccessToken, newRefreshToken) => {
            YounifyConnectSDK.completeTokenRenewal(renewalId, newAccessToken, newRefreshToken);
          };
          tokenHandler.onRenew(evt.expiredAccessToken, evt.refreshToken, renewed);
        }));
        this._tokenHandlerSubscriptions.push(connectEvt.addListener("Token_onRenewedTokens", evt => {
          tokenHandler.onRenewed(evt.newAccessToken, evt.newRefreshToken);
        }));
      }
    }
    return this.callBridge(() => YounifyConnectSDK.configure({
      ...options
    }), res => res);
  }
  setUserTokens(accessToken, refreshToken) {
    return this.callBridge(() => YounifyConnectSDK.setUserTokens(accessToken, refreshToken), res => res);
  }
  requestUserConsent(cancellationTicket) {
    const cancellationTicketId = this.checkCancellationTicketAndGetId(cancellationTicket);
    return this.callBridge(() => YounifyConnectSDK.requestUserConsent(cancellationTicketId), res => res);
  }
  linkService(service, cancellationTicket) {
    const cancellationTicketId = this.checkCancellationTicketAndGetId(cancellationTicket);
    return this.callBridge(() => YounifyConnectSDK.linkService({
      ...service
    }, cancellationTicketId), res => {
      let linkServiceResult = LinkServiceResultFactory.createFromJsonObj(res);
      this.updateService(service, linkServiceResult.service);
      return linkServiceResult.success;
    });
  }
  manageLinkedService(service, cancellationTicket) {
    const cancellationTicketId = this.checkCancellationTicketAndGetId(cancellationTicket);
    return this.callBridge(() => YounifyConnectSDK.manageLinkedService({
      ...service
    }, cancellationTicketId), res => {
      let updatedService = StreamingServiceFactory.createFromJsonObj(res);
      this.updateService(service, updatedService);
      return null;
    });
  }
  unlinkService(service, cancellationTicket) {
    const cancellationTicketId = this.checkCancellationTicketAndGetId(cancellationTicket);
    return this.callBridge(() => YounifyConnectSDK.unlinkService({
      ...service
    }, cancellationTicketId), res => {
      let updatedService = StreamingServiceFactory.createFromJsonObj(res);
      this.updateService(service, updatedService);
      return null;
    });
  }
  fetchServices(cancellationTicket) {
    const cancellationTicketId = this.checkCancellationTicketAndGetId(cancellationTicket);
    return this.callBridge(() => YounifyConnectSDK.fetchServices(cancellationTicketId), res => StreamingServiceFactory.createFromJsonArray(res));
  }
  fetchLinkedServices(cancellationTicket) {
    const cancellationTicketId = this.checkCancellationTicketAndGetId(cancellationTicket);
    return this.callBridge(() => YounifyConnectSDK.fetchLinkedServices(cancellationTicketId), res => StreamingServiceFactory.createFromJsonArray(res));
  }
  fetchBrokenServices(cancellationTicket) {
    const cancellationTicketId = this.checkCancellationTicketAndGetId(cancellationTicket);
    return this.callBridge(() => YounifyConnectSDK.fetchBrokenServices(cancellationTicketId), res => StreamingServiceFactory.createFromJsonArray(res));
  }
  fetchCategories(cancellationTicket) {
    const cancellationTicketId = this.checkCancellationTicketAndGetId(cancellationTicket);
    return this.callBridge(() => YounifyConnectSDK.fetchCategories(cancellationTicketId), res => StreamingCategoryFactory.createFromJsonArray(res));
  }
  async fetchContent(categories, services, cancellationTicket, serviceError, categoryServiceComplete) {
    const cancellationTicketId = this.checkCancellationTicketAndGetId(cancellationTicket);
    const requestId = (this._nextRequestId++).toString() + '-' + Date.now().toString(36);
    const subscriptions = new Array();
    const updateService = sourceService => {
      let targetService = services.find(obj => obj.name == sourceService.name);
      this.updateService(targetService, sourceService);
      return targetService ?? StreamingServiceFactory.createFromJsonObj(sourceService);
    };
    const updateServices = res => {
      res.forEach(result => {
        result.services.forEach(resultService => {
          resultService.service = updateService(resultService.service);
        });
      });
    };
    let serviceErrors = false;
    let categoryServiceCompletions = false;
    let allCompletions = true;
    if (serviceError) {
      subscriptions.push(connectEvt.addListener("FetchContent_onServiceError", evt => {
        let evtCategoryServiceError = EventCategoryServiceErrorFactory.createFromJsonObj(evt);
        if (evtCategoryServiceError.requestId == requestId) serviceError(updateService(evtCategoryServiceError.service), evtCategoryServiceError.error);
      }));
      serviceErrors = true;
    }
    if (categoryServiceComplete) {
      subscriptions.push(connectEvt.addListener("FetchContent_onCategoryServiceComplete", evt => {
        let evtCategoryServiceComplete = EventCategoryServiceCompleteFactory.createFromJsonObj(evt);
        if (evtCategoryServiceComplete.requestId == requestId) categoryServiceComplete(evtCategoryServiceComplete.category, updateService(evtCategoryServiceComplete.service), evtCategoryServiceComplete.content, evtCategoryServiceComplete.error);
      }));
      categoryServiceCompletions = true;
      allCompletions = false;
    }
    try {
      return await this.callBridge(() => YounifyConnectSDK.fetchContent(requestId, [...categories].map(c => ({
        ...c
      })), [...services].map(s => ({
        ...s
      })), cancellationTicketId, serviceErrors, categoryServiceCompletions, allCompletions), res => {
        let categoryResults = FetchContentCategoryResultFactory.createFromJsonArray(res);
        updateServices(categoryResults);
        return categoryResults;
      });
    } finally {
      while (subscriptions.length > 0) subscriptions.pop()?.remove();
    }
  }
  fetchContentChildren(content, cancellationTicket) {
    const cancellationTicketId = this.checkCancellationTicketAndGetId(cancellationTicket);
    return this.callBridge(() => YounifyConnectSDK.fetchContentChildren({
      ...content
    }, cancellationTicketId), res => StreamingContentFactory.createFromJsonArray(res));
  }
  fetchContentDetails(content, cancellationTicket) {
    const cancellationTicketId = this.checkCancellationTicketAndGetId(cancellationTicket);
    return this.callBridge(() => YounifyConnectSDK.fetchContentDetails({
      ...content
    }, cancellationTicketId), res => StreamingContentDetailsFactory.createFromJsonObj(res));
  }
  async searchContent(services, searchPhrase, cancellationTicket, serviceComplete) {
    const cancellationTicketId = this.checkCancellationTicketAndGetId(cancellationTicket);
    const requestId = (this._nextRequestId++).toString() + '-' + Date.now().toString(36);
    const subscriptions = new Array();
    const updateService = sourceService => {
      let targetService = services.find(obj => obj.name == sourceService.name);
      this.updateService(targetService, sourceService);
      return targetService ?? StreamingServiceFactory.createFromJsonObj(sourceService);
    };
    const updateServices = res => {
      res.forEach(serviceResult => {
        serviceResult.service = updateService(serviceResult.service);
      });
    };
    let serviceCompletions = false;
    let allCompletions = true;
    if (serviceComplete) {
      subscriptions.push(connectEvt.addListener("SearchContent_onServiceComplete", evt => {
        let evtServiceComplete = EventSearchContentServiceCompleteFactory.createFromJsonObj(evt);
        if (evtServiceComplete.requestId == requestId) serviceComplete(updateService(evtServiceComplete.service), evtServiceComplete.content, evtServiceComplete.error);
      }));
      serviceCompletions = true;
      allCompletions = false;
    }
    try {
      return await this.callBridge(() => YounifyConnectSDK.searchContent(requestId, [...services].map(s => ({
        ...s
      })), searchPhrase, cancellationTicketId, serviceCompletions, allCompletions), res => {
        let searchResults = SearchContentServiceResultFactory.createFromJsonArray(res);
        updateServices(searchResults);
        return searchResults;
      });
    } finally {
      while (subscriptions.length > 0) subscriptions.pop()?.remove();
    }
  }
  fetchImage(url, cancellationTicket) {
    const cancellationTicketId = this.checkCancellationTicketAndGetId(cancellationTicket);
    return this.callBridge(() => YounifyConnectSDK.fetchImage(url, cancellationTicketId), res => res);
  }
}
//# sourceMappingURL=index.js.map