# Advanced Banners

Advanced Banners let you define responsive, context-aware banner ad layouts that adapt to device type, screen orientation, and screen size. Unlike regular banners (which support only top/bottom positioning), Advanced Banners allow you to place multiple banners at arbitrary positions on the screen and automatically switch layouts when conditions change.

### Checking Support

```javascript
var _supported = playgama_bridge_advertisement_is_advanced_banners_supported()
if (_supported) {
    // Advanced Banners are available
}
```

### Usage

#### Method 1: Explicit API Call

Show and hide Advanced Banners directly from your game code:

```javascript
// Show banners for a specific placement
playgama_bridge_advertisement_show_advanced_banners("main_menu")

// Hide banners
playgama_bridge_advertisement_hide_advanced_banners()
```

If `placementFallback` is set in the config, you can call without arguments:

```javascript
playgama_bridge_advertisement_show_advanced_banners("")
```

#### Method 2: Automatic via Platform Messages

Advanced Banners automatically react to platform messages. When you call `playgama_bridge_platform_send_message()` or `playgama_bridge_platform_send_custom_message()`, the system checks if a matching placement exists in the config and triggers it.

```javascript
// This will automatically show banners if "level_paused" placement is configured
playgama_bridge_platform_send_message("level_paused", "")

// This will hide banners if "level_resumed" has action: "hide"
playgama_bridge_platform_send_message("level_resumed", "")

// Custom messages work the same way
playgama_bridge_platform_send_custom_message("shop_opened", "")
```

This is the recommended approach because it ties banner visibility to your game's lifecycle without extra code.

#### Tracking State

You can check the current state at any time:

```javascript
var _state = playgama_bridge_advertisement_advanced_banners_state()
// Possible values: "loading", "shown", "hidden", "failed"
```

To listen for state changes, handle the Async Social event (`Other_70.gml`):

```javascript
if (async_load[? "type"] == "playgama_bridge_advertisement_advanced_banners_state_changed") {
    switch (async_load[? "data"]) {
        case "loading":
            // Banners are being loaded
            break
        case "shown":
            // Banners are visible
            break
        case "hidden":
            // Banners were hidden
            break
        case "failed":
            // Banners failed to load
            break
    }
}
```

### Automatic Behavior

#### Fullscreen Ad Coordination

Advanced Banners are automatically hidden when an interstitial or rewarded ad starts (loading or opened) and automatically restored when the ad finishes (closed or failed). No additional code is needed.

```
Interstitial starts → Advanced Banners hidden
Interstitial ends   → Advanced Banners restored

Rewarded starts     → Advanced Banners hidden
Rewarded ends       → Advanced Banners restored
```

#### Responsive Re-evaluation

When the screen orientation changes or the window is resized, the system automatically re-evaluates conditions and switches to a better-matching variant if one exists. This happens with a 200ms debounce to avoid excessive updates.

For example, if a user rotates their phone from portrait to landscape, and your config has different layouts for each orientation, the banners will seamlessly switch.

### Complete Example

#### Config

```json
{
    "advertisement": {
        "advancedBanners": {
            "placementFallback": "gameplay_stopped",
            "gameplay_started": {
                "action": "hide"
            },
            "gameplay_stopped": {
                "action": "show",
                "default": [
                    { "width": "300px", "height": "250px", "bottom": "10%", "right": "5%" }
                ],
                "mobile:portrait": [
                    { "width": "320px", "height": "50px", "bottom": "0", "left": "0" }
                ],
                "mobile:landscape": [
                    { "width": "300px", "height": "250px", "top": "50%", "right": "0" }
                ],
                "desktop:w>1200": [
                    { "width": "160px", "height": "600px", "top": "10%", "left": "1%" },
                    { "width": "160px", "height": "600px", "top": "10%", "right": "1%" }
                ],
                "desktop:w<=1200": [
                    { "width": "728px", "height": "90px", "bottom": "0", "left": "50%" }
                ],
                "desktop:landscape:ar>=1.78": [
                    { "width": "200px", "height": "600px", "top": "5%", "left": "0" },
                    { "width": "200px", "height": "600px", "top": "5%", "right": "0" },
                    { "width": "970px", "height": "90px", "bottom": "0", "left": "50%" }
                ]
            },
            "<your_placement_here>": {
                "default": [
                    { "width": "728px", "height": "90px", "bottom": "0", "left": "50%" }
                ]
            },
            "<your_placement_here>": {
                "action": "hide"
            }
        }
    }
}
```

#### Game Code

**Create Event (`Create_0.gml`):**

```gml
playgama_bridge_platform_send_message("game_ready", "")
```

**Game Logic (e.g. in a Step or button handler):**

```javascript
// Game lifecycle messages automatically trigger banners
playgama_bridge_platform_send_message("gameplay_started", "")   // hides banners
playgama_bridge_platform_send_message("gameplay_stopped", "")   // shows banners (best layout auto-selected)

// Custom messages for game-specific screens
playgama_bridge_platform_send_custom_message("your_placement_here", "")  // shows banners
playgama_bridge_platform_send_custom_message("your_placement_here", "")  // hides banners

// Or call directly
playgama_bridge_advertisement_show_advanced_banners("gameplay_stopped")
playgama_bridge_advertisement_hide_advanced_banners()
```

**Async Social Event (`Other_70.gml`):**

```javascript
if (async_load[? "type"] == "playgama_bridge_advertisement_advanced_banners_state_changed") {
    switch (async_load[? "data"]) {
        case "loading":
            // Banners are being loaded
            break
        case "shown":
            // Banners are visible
            break
        case "hidden":
            // Banners were hidden
            break
        case "failed":
            // Banners failed to load
            break
    }
}
```

### Configuration

Advanced Banners are configured in `playgama-bridge-config.json` under `advertisement.advancedBanners`.

```json
{
    "advertisement": {
        "advancedBanners": {
            "disable": false,
            "placementFallback": "main_menu",
            "main_menu": {
                "default": [
                    { "width": "300px", "height": "250px", "top": "10%", "right": "10%" }
                ]
            },
            "level_paused": {
                "action": "show",
                "default": [
                    { "width": "300px", "height": "250px", "top": "10%", "right": "10%" }
                ],
                "mobile:portrait": [
                    { "width": "100%", "height": "80px", "bottom": "0", "left": "0" }
                ],
                "desktop:landscape:w>1200": [
                    { "width": "160px", "height": "600px", "top": "10%", "left": "2%" },
                    { "width": "160px", "height": "600px", "top": "10%", "right": "2%" }
                ]
            },
            "level_resumed": {
                "action": "hide"
            }
        }
    }
}
```

#### General Options

| Parameter           | Type    | Default | Description                                                                                                         |
| ------------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------- |
| `disable`           | boolean | `false` | Disable Advanced Banners entirely, even if the platform supports them                                               |
| `placementFallback` | string  | —       | Default placement to use when `playgama_bridge_advertisement_show_advanced_banners()` is called without a placement |

#### Placement Configuration

Each key under `advancedBanners` (other than `disable` and `placementFallback`) defines a **placement**. A placement is identified by a string that matches either:

* A built-in platform message (e.g. `game_ready`, `level_paused`, `gameplay_started`)
* A custom message ID passed to `playgama_bridge_platform_send_custom_message()`
* A string passed directly to `playgama_bridge_advertisement_show_advanced_banners()`

Each placement contains:

| Property        | Type                 | Default  | Description                                                               |
| --------------- | -------------------- | -------- | ------------------------------------------------------------------------- |
| `action`        | `"show"` \| `"hide"` | `"show"` | Whether to show or hide banners when this placement is triggered          |
| `default`       | array                | —        | Fallback banner layout when no condition-based variant matches            |
| *condition key* | array                | —        | Banner layout for a specific set of conditions (see Condition Keys below) |

#### Banner Object

Each banner in the array is an object with CSS positioning values:

| Property | Type   | Description                           |
| -------- | ------ | ------------------------------------- |
| `width`  | string | CSS width (e.g. `"300px"`, `"100%"`)  |
| `height` | string | CSS height (e.g. `"250px"`, `"80px"`) |
| `top`    | string | CSS top offset (e.g. `"0"`, `"10%"`)  |
| `bottom` | string | CSS bottom offset                     |
| `left`   | string | CSS left offset                       |
| `right`  | string | CSS right offset                      |

You can define multiple banners per variant to show several ads simultaneously:

```json
"desktop:landscape": [
    { "width": "160px", "height": "600px", "top": "10%", "left": "2%" },
    { "width": "160px", "height": "600px", "top": "10%", "right": "2%" },
    { "width": "728px", "height": "90px", "bottom": "0", "left": "50%" }
]
```

### Condition Keys

Condition keys are colon-separated segments that describe when a variant should be used. The system evaluates all keys against the current environment and picks the best match.

#### Available Segments

| Segment          | Example                             | Description                                                                                                                          |
| ---------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Device type      | `mobile`, `desktop`, `tablet`, `tv` | Matches the current device type                                                                                                      |
| Orientation      | `portrait`, `landscape`             | Matches the current screen orientation                                                                                               |
| Width condition  | `w>600`, `w<=1024`, `w>=768`        | Matches against window width (or canvas width if `canvas` segment is present)                                                        |
| Height condition | `h>400`, `h<=900`                   | Matches against window height (or canvas height)                                                                                     |
| Aspect ratio     | `ar>1.5`, `ar>=1.78`, `ar<=1.0`     | Matches screen width/height ratio                                                                                                    |
| Canvas mode      | `canvas`                            | Use game canvas dimensions instead of window size for all `w`/`h`/`ar` conditions. If no canvas is found, the variant will not match |

#### Combining Segments

Combine segments with `:` to create compound conditions. All segments must match for the variant to be selected:

```json
{
    "mobile:portrait": [...],
    "mobile:portrait:w>400": [...],
    "desktop:landscape:w>1200:ar>=1.5": [...],
    "tablet:canvas:w>800": [...]
}
```

#### Priority Scoring

When multiple variants match, the one with the highest score wins:

| Segment Type                            | Score |
| --------------------------------------- | ----- |
| Device type (`mobile`, `desktop`, etc.) | +4    |
| Orientation (`portrait`, `landscape`)   | +2    |
| Canvas mode (`canvas`)                  | +1    |
| Each dimension/aspect ratio condition   | +1    |

If two variants have the same score, the one with **more segments** wins. If they also have the same number of segments, the one whose dimension/aspect ratio threshold is **closest to the actual value** takes priority.

**Example**: screen is 1300px wide, device is desktop

| Key                        | Matches?       | Score                        |
| -------------------------- | -------------- | ---------------------------- |
| `default`                  | yes (fallback) | -1                           |
| `desktop`                  | yes            | 4                            |
| `desktop:w>500`            | yes            | 4 + 1 = 5                    |
| `desktop:w>1200`           | yes            | 5 + higher specificity bonus |
| `desktop:landscape:w>1200` | yes            | 4 + 2 + 1 = 7                |
| `mobile:portrait`          | no             | —                            |
