import torch
from torch.utils.data import Dataset, DataLoader
from torch.nn.utils.rnn import pad_sequence

texts = [
    [5, 9, 12, 34, 23, 76, 89],          # len = 7
    [2, 45, 23],                         # len = 3
    [12, 56, 78, 90, 43, 22, 11, 8],     # len = 8
    [65, 12, 99, 54],                    # len = 4
    [3, 7, 8, 5, 1, 4, 6, 10, 11],       # len = 9
]

labels = [0, 1, 0, 2, 1]

class TextDataset(Dataset):
    def __init__(self, texts, labels):
        # сложите тексты и классы в переменные датасета
        self.texts = texts
        self.labels = labels

    def __len__(self):
        # посчитайте размер датасета
        return len(self.texts)

    def __getitem__(self, idx):
        # верните элемент датасета
        return {
            'text': torch.tensor(self.texts[idx], dtype=torch.long),
            'label': torch.tensor(self.labels[idx], dtype=torch.long)
        }

def collate_fn(batch):
    texts = [item['text'] for item in batch]
    labels = [item['label'] for item in batch]

    # посчитайте длины текстов в батче
    lengths = []
    for _ in range(len(texts)): 
        lengths.append(len(texts[_]))

    # отсортируйте тексты и классы по убыванию длины текстов
    joined_data = list(zip(lengths, texts, labels))
    # joined_data = torch.cat(
    #     torch.tensor(lengths), 
    #     torch.tensor(texts), 
    #     labels
    #     )
    joined_data.sort(key=lambda x: x[0], reverse=True)
    # joined_data = torch.argsort(joined_data, dim=0)
    lengths, texts, labels = zip(*joined_data)
    # lengths, texts, labels = torch.split(joined_data, 0)

    # дополните тексты пэддингом
    padded_texts = pad_sequence(texts, batch_first=True, padding_value=0)

    # посчитайте маску для батча
    masks = (padded_texts != 0).long()

    return {
        'texts': padded_texts,     # (batch_size, max_len)
        'masks': masks,            # (batch_size, max_len)
        'labels': labels,          # (batch_size,)
        'lengths': lengths
    }

dataset = TextDataset(texts, labels)

# создайте объект dataloader с batch_size=3 и реализованным collate_fn
dataloader = DataLoader(dataset, batch_size=3, collate_fn=collate_fn)

# вывод результатов
for batch in dataloader:
    print("Texts:\n", batch['texts'])
    print("Masks:\n", batch['masks'])
    print("Labels:", batch['labels'])
    # print("Lengths:", batch['lengths'])
    print("=" * 40)