#import "modules/std.sx";
#import "platform.sx";

// Who can see an app in listings: `private` = owner only, `unlisted` =
// reachable by direct link, `public` = listed.
Visibility :: enum u8 {
    private;
    unlisted;
    public;
}

// A reverse-DNS bundle identifier (e.g. "co.acme.app") for one platform.
// An app carries at most one per platform; kept as a flat list scanned
// linearly (no HashMap yet).
BundleId :: struct {
    platform: Platform;
    value: string;
}

// How this app's iOS artifact may be installed (PLAN.md "iOS Install
// Policy"). A normal iPhone cannot install an arbitrary IPA from a web
// page, so the install surface must never imply it can:
//   artifact_only — the IPA is downloadable, presented as bytes, never as
//                   an on-device install action (the safe default);
//   testflight    — installation happens through Apple's TestFlight flow
//                   (requires `testflight_url`);
//   enterprise    — enrolled devices install over-the-air via a signed
//                   HTTPS manifest plist (requires an iOS bundle id).
IosMode :: enum u8 {
    artifact_only;
    testflight;
    enterprise;
}

// A distributable application. `slug` is the URL-safe handle; `id` is the
// opaque primary key. Timestamps are unix epoch seconds.
App :: struct {
    id: string;
    slug: string;
    display_name: string;
    bundle_ids: List(BundleId);
    owner: string;
    visibility: Visibility = .private;
    ios_mode: IosMode = .artifact_only;
    testflight_url: string = "";
    created_at: i64;
    updated_at: i64;
}

// The app's bundle identifier for `platform`, "" when none is set.
bundle_id_for :: (a: App, p: Platform) -> string {
    i := 0;
    while i < a.bundle_ids.len {
        if a.bundle_ids.items[i].platform == p { return a.bundle_ids.items[i].value; }
        i += 1;
    }
    return "";
}
