# ТЗ для Android-разработчика
## Доработка Player: поддержка виджетов в виртуальных макетах

## 1. Цель задачи

Необходимо доработать Android-плеер так, чтобы он корректно воспроизводил контент вместе с виджетами, которые приходят из CMS через API `v4/device/data`.

Плеер должен уметь:

1. получать из API состав виртуального макета;
2. отображать основной контент и html-виджеты одновременно в рамках одного экрана;
3. корректно показывать виджеты:
    - на филлерах плеера;
    - на роликах рекламной кампании;
4. переключать макеты/контент без визуальных артефактов, насколько это возможно;
5. подставлять в html-виджет данные, пришедшие в `content_package.data`.

---

# 2. Контекст и источник данных

Источник данных для плеера: API CMS `v4/device/data`. На стороне CMS уже настроено следующее:

- CMS отдает контент и виджеты в одном ответе;
- виджет может быть:
    - частью макета устройства для показа во время филлеров;
    - частью макета кампании для показа во время роликов кампании;
- визуальный макет задает разбиение экрана на области;
- в одну область макета помещается основной медиа-контент;
- в другую область помещается html-виджет.

То есть на стороне Android не требуется создавать/редактировать виджеты.  
Задача Android-плеера — **корректно интерпретировать ответ API и воспроизводить результат**.

---

# 3. Бизнес-логика

## 3.1. Общая логика воспроизведения

Плеер получает от API `content_package`, внутри которого есть:

- `triggers` — расписания/триггеры;
- `playback_items` — элементы воспроизведения;
- `files` — файлы контента;
- `data` — данные для виджетов;
- `fillers` — филлеры;
- `audio_playback_items` — аудиоэлементы.

Каждый `playback_item` может содержать несколько `content_items`.

В рамках данной задачи важно, что один `playback_item` может содержать одновременно:

- основной контент (`image`, `video`);
- html-виджет (`type = html`, `context = widget`).

Плеер должен рендерить все `content_items` одного `playback_item` **одновременно**, согласно координатам `playback_item_data.position`.

---

## 3.2. Где должны показываться виджеты

### Сценарий A. Виджет на филлерах устройства
Если у устройства закреплен визуальный макет с виджетом, то при показе филлерного контента плеер должен отображать:

- основной контент филлера в своей области;
- виджет в своей области.

### Сценарий B. Виджет на кампании
Если у кампании выбран визуальный макет с виджетом, то при показе роликов/креативов кампании плеер должен отображать:

- основной контент кампании в своей области;
- виджет в своей области.

---

## 3.3. Важное замечание по переключению между макетами

В CMS могут быть созданы разные визуальные макеты:

- один для устройства/филлеров;
- другой для кампании.

Например:
- у устройства виджет снизу;
- у кампании виджет справа.

Из-за этого при переходах между филлерами и кампанией возможны визуальные скачки макета.  
Плеер должен уметь это обрабатывать максимально корректно:

- полностью перестраивать layout при смене `playback_item`;
- не оставлять артефактов предыдущего виджета/контента;
- не показывать старый html-виджет поверх нового макета;
- не растягивать виджет на старую область.

---

# 4. Что именно нужно реализовать в Android Player

## 4.1. Поддержка многозонного воспроизведения одного playback_item

Если `playback_item.content_items` содержит несколько элементов, плеер должен:

1. создать единый контейнер под весь экран;
2. для каждого `content_item` создать отдельную область по координатам:
    - `x`
    - `y`
    - `width`
    - `height`
3. одновременно отрисовать все зоны.

### Пример из JSON

Для `playback_item.id = 556` есть 2 зоны:

#### Зона 1 — основной контент

    {
      "type": "image",
      "playback_item_data": {
        "position": {
          "x": 0,
          "y": 0,
          "width": 1440,
          "height": 1080
        }
      }
    }

#### Зона 2 — виджет

    {
      "type": "html",
      "playback_item_data": {
        "position": {
          "x": 1440,
          "y": 0,
          "width": 480,
          "height": 1080
        }
      }
    }

Итоговый экран: `1920x1080`, где:

- слева `1440x1080` — медиа;
- справа `480x1080` — html-виджет.

---

## 4.2. Поддержка `type = html` и `context = widget`

Если `content_item.type = html` и `content_item_data.context = widget`, плеер должен:

1. скачать html-архив/ресурс из `files`;
2. подготовить локальное отображение виджета;
3. открыть его внутри WebView;
4. передать в него данные из `content_item_data.data`.

---

## 4.3. Поддержка данных вида `$playback-data`

В JSON виджет ссылается не на встроенные значения, а на данные по ссылке:

    "data": {
      "weather": {
        "$playback-data": 1
      },
      "forecast": {
        "$playback-data": 2
      }
    }

Это означает:

- нужно взять объект из `content_package.data`, где `id = 1`, и подставить его как `weather`;
- нужно взять объект из `content_package.data`, где `id = 2`, и подставить его как `forecast`.

### Требуемое поведение

Плеер должен уметь резолвить ссылки вида:

    { "$playback-data": N }

в реальный объект из массива:

    content_package.data[]

по полю `id`.

### Ожидаемый результат

Перед загрузкой html-виджета плеер должен сформировать итоговый JSON-конфиг виджета, где вместо ссылок уже лежат реальные данные.

---

## 4.4. Передача данных в WebView

Способ передачи можно реализовать любым технически надежным способом, но результат должен быть таким, чтобы html-виджет получил:

- `options` — параметры виджета;
- `data.weather` — текущую погоду;
- `data.forecast` — прогноз.

Допустимые варианты реализации:

- через JS bridge;
- через инъекцию JSON в страницу;
- через локальный endpoint;
- через query params / local file mapping.

Главное требование: виджет должен получать финальный resolved JSON, а не сырые ссылки `$playback-data`.

---

## 4.5. Поведение при ошибках виджета

Если html-виджет:

- не скачался;
- не распаковался;
- не открылся;
- упал;

то:

1. основной контент продолжает воспроизводиться;
2. зона виджета пустая или fallback;
3. приложение не падает;
4. ошибка логируется.

---

# 5. Нефункциональные требования

## Стабильность

Не падать.

## Производительность

Не плодить WebView.

## Логи

Логировать всё ключевое.

---

# 6. Критерии приемки

✔ Виджет и контент вместе  
✔ Данные подставляются  
✔ Длительность корректна  
✔ Нет артефактов  
✔ Нет падений
