// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_utils.h"
#import "base/check.h"
#import "ios/chrome/browser/shared/model/web_state_list/tab_group.h"
#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_item_identifier.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_group_item.h"
#import "ios/chrome/browser/ui/tab_switcher/web_state_tab_switcher_item.h"
NSArray<GridItemIdentifier*>* CreateTabItems(WebStateList* web_state_list,
TabGroupRange range) {
NSMutableArray<GridItemIdentifier*>* items = [[NSMutableArray alloc] init];
for (int index : range) {
web::WebState* web_state = web_state_list->GetWebStateAt(index);
[items addObject:[GridItemIdentifier tabIdentifier:web_state]];
}
return items;
}
NSArray<GridItemIdentifier*>* CreateItems(WebStateList* web_state_list) {
NSMutableArray<GridItemIdentifier*>* items = [[NSMutableArray alloc] init];
int first_index = web_state_list->pinned_tabs_count();
DCHECK(first_index == 0 || IsPinnedTabsEnabled());
int incrementer = 1;
for (int i = first_index; i < web_state_list->count(); i += incrementer) {
DCHECK(!web_state_list->IsWebStatePinnedAt(i));
const TabGroup* tab_group = web_state_list->GetGroupOfWebStateAt(i);
if (tab_group) {
[items addObject:[GridItemIdentifier groupIdentifier:tab_group
withWebStateList:web_state_list]];
// Skip the webStates that belong to `group_item`.
incrementer = tab_group->range().count();
} else {
web::WebState* web_state = web_state_list->GetWebStateAt(i);
[items addObject:[GridItemIdentifier tabIdentifier:web_state]];
incrementer = 1;
}
}
return items;
}
int WebStateIndexFromGridDropItemIndex(WebStateList* web_state_list,
NSUInteger drop_item_index,
int previous_web_state_index) {
if (!IsPinnedTabsEnabled() && !IsTabGroupInGridEnabled()) {
return drop_item_index;
}
if (drop_item_index == NSNotFound) {
return WebStateList::kInvalidIndex;
}
// Shift `web_state_index` by the number of pinned WebStates.
int web_state_index = web_state_list->pinned_tabs_count();
// Shift `web_state_index` by the number of WebStates in the
// groups before it.
for (NSUInteger i = 0;
i < drop_item_index && web_state_index < web_state_list->count(); ++i) {
CHECK(web_state_list->ContainsIndex(web_state_index),
base::NotFatalUntil::M128);
const TabGroup* tabGroup =
web_state_list->GetGroupOfWebStateAt(web_state_index);
if (tabGroup) {
web_state_index += tabGroup->range().count();
} else {
web_state_index++;
}
}
// If there is no information about `previous_web_state_index`, the current
// `web_state_index` is considered valid.
if (previous_web_state_index == WebStateList::kInvalidIndex) {
return web_state_index;
}
// If the current `web_state_index` belongs to a group and
// `previous_web_state_index` is smaller than `web_state_index`,
// update the `web_state_index` to be the latest index of the
// group.
if (previous_web_state_index < web_state_index &&
web_state_index < web_state_list->count()) {
const TabGroup* tabGroup =
web_state_list->GetGroupOfWebStateAt(web_state_index);
if (tabGroup) {
web_state_index = tabGroup->range().range_end() - 1;
}
}
return web_state_index;
}
int WebStateIndexAfterGridDropItemIndex(WebStateList* web_state_list,
NSUInteger drop_item_index,
int previous_web_state_index) {
int web_state_index = WebStateIndexFromGridDropItemIndex(
web_state_list, drop_item_index, previous_web_state_index);
// When an item is moved to the right, we have to shift the `web_state_index`
// by one. This adjustment is necessary because UIKit excludes the dragged
// item from the calculation of the `drop_item_index`.
if (previous_web_state_index != WebStateList::kInvalidIndex &&
previous_web_state_index < web_state_index) {
web_state_index += 1;
}
return web_state_index;
}