1/*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
3 */
4import { ObservedArray } from '../data/ObservedArray';
5import { BaseState, ViewState } from './ViewState';
6
7/**
8 *
9 * @param <VS> 页面状态
10 * @param <VD> 页面数据
11 */
12export abstract class AbsBaseViewData<VS extends ViewState, VD> implements IDataSource {
13
14  private listeners: DataChangeListener[] = []
15  /**
16   * view state
17   */
18  private state: VS;
19  /**
20   * view live date list
21   */
22  private liveData: ObservedArray<VD> = new ObservedArray<VD>();
23
24  /**
25   * 构造函数
26   */
27  protected constructor() {
28    this.state = this.initViewState();
29  }
30
31  totalCount(): number {
32    return this.liveData.length
33  }
34
35  registerDataChangeListener(listener: DataChangeListener) {
36    if (this.listeners.indexOf(listener) < 0) {
37      this.listeners.push(listener)
38    }
39  }
40
41  unregisterDataChangeListener(listener: DataChangeListener): void {
42    const pos = this.listeners.indexOf(listener);
43    if (pos >= 0) {
44      this.listeners.splice(pos, 1)
45    }
46  }
47
48  public getData(index: number): VD {
49    return this.liveData[index]
50  }
51
52  private initViewState(): VS {
53    return this.createViewState();
54  }
55
56  protected abstract createViewState(): VS;
57
58  public getState(): VS {
59    return this.state;
60  }
61
62  /**
63   * start loading
64   */
65  public loading(): void {
66    if (this.isEmpty()) {
67      this.state?.setViewState(BaseState.LOADING);
68    }
69  }
70
71  public normal(newData: ObservedArray<VD>): void {
72    this.clear()
73    this.liveData.push(...newData);
74    this.notifyDataReload()
75    this.state.setViewState(BaseState.NORMAL);
76  }
77
78  /**
79   * finish loading without data
80   */
81  public normalState(): void {
82    this.state?.setViewState(BaseState.NORMAL);
83  }
84
85  /**
86   * clear livedata
87   */
88  public clear(): void {
89    this.liveData.splice(0, this.liveData?.length)
90  }
91
92  /**
93   * 获取列表数据,不可变
94   *
95   * @return 不可变列表数据,运行时放通,问题在开发阶段发现问题
96   */
97  public getDataList(): ObservedArray<VD> {
98    return this.liveData;
99  }
100
101  /**
102   * 针对分页的数据,不要使用normal,直接使用append
103   *
104   * @param appendData 需要追加的数据
105   */
106  public append(appendData: VD[]): void {
107    this.liveData.push(...appendData);
108    this.notifyDataReload()
109    this.state.setViewState(BaseState.NORMAL);
110  }
111
112  /**
113   * 针对分页的数据,不要使用normal,直接使用append
114   * @param index index
115   * @param appendData 需要追加的数据
116   */
117  public appendByIndex(index: number, appendData: VD[]): void {
118    this.liveData.splice(index, 0, ...appendData);
119    this.notifyDataAdd(index);
120    this.notifyDataReload()
121    this.state.setViewState(BaseState.NORMAL);
122  }
123
124  /**
125   * finish loading without data (only one data)
126   *
127   * @param newData newData
128   */
129  public appendSingle(newData: VD): void {
130    this.liveData.push(newData);
131    this.state.setViewState(BaseState.NORMAL);
132  }
133
134  /**
135   * 移除
136   *
137   * @param index 位置
138   */
139  public remove(index: number): void {
140    this.liveData.splice(index, 1)
141    this.notifyDataDelete(index)
142    this.notifyDataReload()
143  }
144
145  /**
146   * 设置数据是否为空,涉及nodata页面展示
147   *
148   * @return 数据是否为空
149   */
150  public isEmpty(): boolean {
151    return this.liveData.length === 0;
152  }
153
154  notifyDataReload(): void {
155    this.listeners.forEach(listener => {
156      listener.onDataReloaded()
157    })
158  }
159
160  notifyDataAdd(index: number): void {
161    this.listeners.forEach(listener => {
162      listener.onDataAdd(index)
163    })
164  }
165
166  notifyDataChange(index: number): void {
167    this.listeners.forEach(listener => {
168      listener.onDataChange(index)
169    })
170  }
171
172  notifyDataDelete(index: number): void {
173    this.listeners.forEach(listener => {
174      listener.onDataDelete(index)
175    })
176  }
177
178  notifyDataMove(from: number, to: number): void {
179    this.listeners.forEach(listener => {
180      listener.onDataMove(from, to)
181    })
182  }
183}