1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "page_tree.h"
17
18#include "tree_manager.h"
19
20namespace OHOS {
21namespace WuKong {
22namespace {
23const uint8_t PAGE_COUNT_POSION = 50;
24const uint8_t PAGE_NODE_COUNT_POSION = 36;
25const uint8_t PAGE_BRANCH_COUNT_POSION = 28;
26const uint8_t PAGE_HEIGHT_POSION = 22;
27const uint8_t PAGE_TWO_LAYER_WIDTH_POSION = 14;
28const uint8_t PAGE_LAST_LAYER_WIDTH_POSION = 0;
29uint64_t pageCount = 0;
30uint64_t nodeCount = 0;
31uint64_t branchCount = 0;
32uint32_t layer = 0;
33uint32_t height = 0;
34uint32_t lastWidth = 0;
35bool g_isLeftBranch = false;
36void RecursStatistics(std::shared_ptr<ComponentTree> parent)
37{
38    // all page node count Statistics
39    pageCount++;
40    uint32_t childCount = parent->GetChildren().size();
41
42    // layer pointer move to next
43    layer++;
44    if (childCount == 0) {
45        // node Statistics
46        nodeCount++;
47    } else {
48        // branch Statistics
49        branchCount++;
50        if (layer >= height) {
51            // tree max height Statistics
52            height++;
53
54            // last tree width.
55            lastWidth = childCount;
56        }
57    }
58
59    // recurs child.
60    for (auto child : parent->GetChildren()) {
61        RecursStatistics(std::static_pointer_cast<ComponentTree>(child));
62    }
63    // layer pointer move to previous
64    layer--;
65}
66}  // namespace
67
68/**
69 * @brief Page Node Id specification format
70 * @details
71 * |----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|
72 * |ALL COUNT -14   |NODECOUNT-14|BRHCNT -8|TRH |TWO WIDTH -14   |LAST WIDTH -14   |
73 */
74bool PageTree::SetNodeId()
75{
76    nodeId_ = 0;
77    auto componentTree = TreeManager::GetInstance()->GetNewComponents();
78    if (componentTree->GetNodeId() == 0) {
79        WARN_LOG("Component Tree is Empty");
80        return false;
81    }
82    if (componentTree->GetParent() != nullptr) {
83        WARN_LOG("Component Tree is not root");
84        return false;
85    }
86
87    // init statistics variables
88    pageCount = 0;
89    nodeCount = 0;
90    branchCount = 0;
91    height = 1;
92    layer = 0;
93    lastWidth = 0;
94    g_isLeftBranch = true;
95
96    // recurs statistics
97    RecursStatistics(componentTree);
98
99    uint32_t twoWidth = componentTree->GetChildren().size();
100    DEBUG_LOG_STR("Page Count: (%d), Node: (%d), Branch: (%d), Height: (%d), Two Width: (%d), Last Width: (%d)",
101                  (uint32_t)pageCount, (uint32_t)nodeCount, (uint32_t)branchCount, height, lastWidth, twoWidth);
102    count_ = (uint32_t)pageCount;
103
104    // make node id for compare page.
105    nodeId_ |= pageCount << PAGE_COUNT_POSION;
106    nodeId_ |= nodeCount << PAGE_NODE_COUNT_POSION;
107    nodeId_ |= branchCount << PAGE_BRANCH_COUNT_POSION;
108    nodeId_ |= height << PAGE_HEIGHT_POSION;
109    nodeId_ |= twoWidth << PAGE_TWO_LAYER_WIDTH_POSION;
110    nodeId_ |= lastWidth << PAGE_LAST_LAYER_WIDTH_POSION;
111    TRACK_LOG_STR("Page Node ID: (0x%016llX)", nodeId_);
112    // make node id for compare page.
113    auto elementInfo = TreeManager::GetInstance()->GetNewElementInfoList((count_ - 1));
114    if (elementInfo == nullptr) {
115        ERROR_LOG("get new element info is nullptr");
116        return false;
117    }
118    std::string pagePath = elementInfo->GetPagePath();
119    TreeManager::GetInstance()->SetOldPagePath(pagePath);
120    TRACK_LOG_STR("Componentpage path: (%s)", pagePath.c_str());
121    return true;
122}
123}  // namespace WuKong
124}  // namespace OHOS
125