1e484b35bSopenharmony_ci/*
2e484b35bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3e484b35bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e484b35bSopenharmony_ci * you may not use this file except in compliance with the License.
5e484b35bSopenharmony_ci * You may obtain a copy of the License at
6e484b35bSopenharmony_ci *
7e484b35bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e484b35bSopenharmony_ci *
9e484b35bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e484b35bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e484b35bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e484b35bSopenharmony_ci * See the License for the specific language governing permissions and
13e484b35bSopenharmony_ci * limitations under the License.
14e484b35bSopenharmony_ci */
15e484b35bSopenharmony_ci
16e484b35bSopenharmony_ci/**
17e484b35bSopenharmony_ci * Intercept callback from native and forward to user-defined callback.
18e484b35bSopenharmony_ci * @param {*} args - Args.
19e484b35bSopenharmony_ci * @param {boolean} [needPromise] - If asynchronous operations are needed.
20e484b35bSopenharmony_ci * @return {Object} If promise are needed, return { args, promise }. Otherwise return args.
21e484b35bSopenharmony_ci */
22e484b35bSopenharmony_ciexport function interceptCallback(args: any, needPromise?: boolean): object {
23e484b35bSopenharmony_ci  if (args.length === 0 && !needPromise) {
24e484b35bSopenharmony_ci    return args;
25e484b35bSopenharmony_ci  }
26e484b35bSopenharmony_ci  const first: object = args[0];
27e484b35bSopenharmony_ci  const callbacks: object = {};
28e484b35bSopenharmony_ci  let hasProperty: boolean = false;
29e484b35bSopenharmony_ci  if (typeof first === 'object' &&
30e484b35bSopenharmony_ci    Object.prototype.toString.call(first).toLowerCase() === '[object object]' &&
31e484b35bSopenharmony_ci    args.length === 1
32e484b35bSopenharmony_ci  ) {
33e484b35bSopenharmony_ci    for (const key in first) {
34e484b35bSopenharmony_ci      const value: Function = first[key];
35e484b35bSopenharmony_ci      if (typeof value === 'function') {
36e484b35bSopenharmony_ci        callbacks[key] = value;
37e484b35bSopenharmony_ci      } else {
38e484b35bSopenharmony_ci        hasProperty = true;
39e484b35bSopenharmony_ci      }
40e484b35bSopenharmony_ci    }
41e484b35bSopenharmony_ci  } else {
42e484b35bSopenharmony_ci    hasProperty = true;
43e484b35bSopenharmony_ci  }
44e484b35bSopenharmony_ci
45e484b35bSopenharmony_ci  let promise: any;
46e484b35bSopenharmony_ci  const callbLength: number = Object.keys(callbacks).length;
47e484b35bSopenharmony_ci  if (needPromise) {
48e484b35bSopenharmony_ci    if (callbLength <= 0) {
49e484b35bSopenharmony_ci      promise = new PromiseRef();
50e484b35bSopenharmony_ci    }
51e484b35bSopenharmony_ci  }
52e484b35bSopenharmony_ci  if (callbLength > 0 || promise) {
53e484b35bSopenharmony_ci    const callb = (msg: { method: string; arguments: any; }) => {
54e484b35bSopenharmony_ci      let func = callbacks[msg.method];
55e484b35bSopenharmony_ci      const callbArgs: any = msg.arguments;
56e484b35bSopenharmony_ci
57e484b35bSopenharmony_ci      if (func !== undefined) {
58e484b35bSopenharmony_ci        func(...callbArgs);
59e484b35bSopenharmony_ci      }
60e484b35bSopenharmony_ci
61e484b35bSopenharmony_ci      // Always call complete().
62e484b35bSopenharmony_ci      func = callbacks['complete'];
63e484b35bSopenharmony_ci      if (func !== undefined) {
64e484b35bSopenharmony_ci        func(...callbArgs);
65e484b35bSopenharmony_ci      }
66e484b35bSopenharmony_ci      if (promise) {
67e484b35bSopenharmony_ci        const data: any = callbArgs &&
68e484b35bSopenharmony_ci          callbArgs.length > 0
69e484b35bSopenharmony_ci          ? callbArgs[0]
70e484b35bSopenharmony_ci          : undefined;
71e484b35bSopenharmony_ci        if ('success' === msg.method || 'callback' === msg.method) {
72e484b35bSopenharmony_ci          promise.resolve({ data });
73e484b35bSopenharmony_ci        } else {
74e484b35bSopenharmony_ci          // 200 means common error ,100 :cancel.
75e484b35bSopenharmony_ci          const code: any =
76e484b35bSopenharmony_ci            'cancel' === msg.method
77e484b35bSopenharmony_ci              ? 100
78e484b35bSopenharmony_ci              : callbArgs && callbArgs.length > 1
79e484b35bSopenharmony_ci                ? callbArgs[1]
80e484b35bSopenharmony_ci                : 200;
81e484b35bSopenharmony_ci          promise.reject({ data, code });
82e484b35bSopenharmony_ci        }
83e484b35bSopenharmony_ci      }
84e484b35bSopenharmony_ci    };
85e484b35bSopenharmony_ci    callb.__onlyPromise = callbLength <= 0;
86e484b35bSopenharmony_ci
87e484b35bSopenharmony_ci    if (hasProperty) {
88e484b35bSopenharmony_ci      args.push(callb);
89e484b35bSopenharmony_ci    } else {
90e484b35bSopenharmony_ci      args = [callb];
91e484b35bSopenharmony_ci    }
92e484b35bSopenharmony_ci  }
93e484b35bSopenharmony_ci  return needPromise ? { args, promise } : args;
94e484b35bSopenharmony_ci}
95e484b35bSopenharmony_ci
96e484b35bSopenharmony_ci/**
97e484b35bSopenharmony_ci * This class provide a Promise object for asynchronous operation processing.
98e484b35bSopenharmony_ci */
99e484b35bSopenharmony_ciclass PromiseRef {
100e484b35bSopenharmony_ci  private _promise: Promise<object>;
101e484b35bSopenharmony_ci  private _reject: Function;
102e484b35bSopenharmony_ci  private _resolve: Function;
103e484b35bSopenharmony_ci
104e484b35bSopenharmony_ci  constructor() {
105e484b35bSopenharmony_ci    this._promise = new Promise((resolve, reject) => {
106e484b35bSopenharmony_ci      this._reject = reject;
107e484b35bSopenharmony_ci      this._resolve = resolve;
108e484b35bSopenharmony_ci    });
109e484b35bSopenharmony_ci  }
110e484b35bSopenharmony_ci
111e484b35bSopenharmony_ci  /**
112e484b35bSopenharmony_ci   * Promise of this PromiseRef.
113e484b35bSopenharmony_ci   * @type {Promise}
114e484b35bSopenharmony_ci   */
115e484b35bSopenharmony_ci  public get promise() {
116e484b35bSopenharmony_ci    return this._promise;
117e484b35bSopenharmony_ci  }
118e484b35bSopenharmony_ci
119e484b35bSopenharmony_ci  public set promise(newPromise) {
120e484b35bSopenharmony_ci    this._promise = newPromise;
121e484b35bSopenharmony_ci  }
122e484b35bSopenharmony_ci
123e484b35bSopenharmony_ci  /**
124e484b35bSopenharmony_ci   * Reject function using the Promise object.
125e484b35bSopenharmony_ci   * @type {Promise}
126e484b35bSopenharmony_ci   */
127e484b35bSopenharmony_ci  public get reject() {
128e484b35bSopenharmony_ci    return this._reject;
129e484b35bSopenharmony_ci  }
130e484b35bSopenharmony_ci
131e484b35bSopenharmony_ci  public set reject(data) {
132e484b35bSopenharmony_ci    this._reject = data;
133e484b35bSopenharmony_ci  }
134e484b35bSopenharmony_ci
135e484b35bSopenharmony_ci  /**
136e484b35bSopenharmony_ci   * Resolve function using the Promise object.
137e484b35bSopenharmony_ci   * @type {Promise}
138e484b35bSopenharmony_ci   */
139e484b35bSopenharmony_ci  public get resolve() {
140e484b35bSopenharmony_ci    return this._resolve;
141e484b35bSopenharmony_ci  }
142e484b35bSopenharmony_ci
143e484b35bSopenharmony_ci  public set resolve(data) {
144e484b35bSopenharmony_ci    this._resolve = data;
145e484b35bSopenharmony_ci  }
146e484b35bSopenharmony_ci}
147