-- todo dev only
drop schema if exists sendou_ink cascade;
drop schema if exists sendou_ink_private cascade;

create extension if not exists "uuid-ossp";

create schema sendou_ink;
create schema sendou_ink_private;

create function sendou_ink_private.set_updated_at() returns trigger as $$
begin
  new.updated_at := current_timestamp;
  return new;
end;
$$ language plpgsql;

-- ACCOUNT

-- no checks because this data is not provided by user but with the log in event
create table sendou_ink.account (
  id                    serial primary key,
  discord_id            text not null,
  discord_username      text not null,
  discord_discriminator text not null,
  discord_avatar        text,
  twitch                text,
  twitter               text,
  youtube_id            text,
  youtube_name          text,
  created_at            timestamp default now(),
  updated_at            timestamp default now()
);

create function sendou_ink.account_discord_full_username(account sendou_ink.account) returns text as $$
  select account.discord_username || '#' || account.discord_discriminator
$$ language sql stable;

create trigger account_updated_at before update
  on sendou_ink.account
  for each row
  execute procedure sendou_ink_private.set_updated_at();

-- ORGANIZATION

create table sendou_ink.organization (
  identifier            text primary key 
                          check (identifier ~ '^[a-z0-9-]{2,50}$'),
  name                  text not null
                          check (char_length(name) < 51),
  discord_invite_code   text not null
                          check (char_length(discord_invite_code) < 51),
  twitter               text 
                          check (twitter ~ '^[a-zA-Z0-9_]{4,15}$'),
  created_at            timestamp default now(),
  updated_at            timestamp default now(),
  owner_id              integer not null references sendou_ink.account(id)
);

create function sendou_ink.organization_twitter_url(organization sendou_ink.organization) returns text as $$
  select 'https://twitter.com/' || organization.twitter
$$ language sql stable;

create function sendou_ink.organization_discord_invite_url(organization sendou_ink.organization) returns text as $$
  select 'https://discord.com/invite/' || organization.discord_invite_code
$$ language sql stable;

create index organization_owner_id on sendou_ink.organization (owner_id);

create trigger organization_updated_at before update
  on sendou_ink.organization
  for each row
  execute procedure sendou_ink_private.set_updated_at();

-- TOURNAMENT

create table sendou_ink.tournament (
  identifier                 text primary key
                               check (identifier ~ '^[a-z0-9-]{2,50}$'),
  name                       text not null
                               check (char_length(name) < 51),
  description                text
                               check (char_length(description) < 5000),
  start_time                 timestamp not null
                              check (start_time > now()),
  check_in_time              timestamp,
  -- TODO check
  banner_background          text not null,
  banner_text_hsl_args       text not null
                              check (banner_text_hsl_args ~ '^[0-9]{1,3} [0-9]{1,3}% [0-9]{1,3}%$'),
  created_at                 timestamp default now(),
  updated_at                 timestamp default now(),
  organization_identifier    text not null references sendou_ink.organization(identifier),
  CHECK (check_in_time < start_time)
);

-- create function sendou_ink.tournament_text_color(tournament sendou_ink.tournament) returns text as $$
--   select 'hsl(' || tournament.banner_text_hsl_args || ')'
-- $$ language sql stable;

create index tournament_organization_identifier on sendou_ink.tournament(organization_identifier);

create trigger tournament_updated_at before update
  on sendou_ink.tournament
  for each row
  execute procedure sendou_ink_private.set_updated_at();

create table sendou_ink.mode_enum (
  name text primary key
);
comment on table sendou_ink.mode_enum is E'@enum';
insert into sendou_ink.mode_enum (name) values
  ('TW'),
  ('SZ'),
  ('TC'),
  ('RM'),
  ('CB');

create table sendou_ink.map_mode (
  id          serial primary key,
  stage       text not null,
  game_mode   text not null references sendou_ink.mode_enum(name),
  unique (stage, game_mode)
);

create table sendou_ink.map_pool (
  tournament_identifier   text not null references sendou_ink.tournament(identifier),
  map_mode_id             integer not null references sendou_ink.map_mode(id),
  unique (tournament_identifier, map_mode_id)
);

create index map_pool_tournament_identifier on sendou_ink.map_pool(tournament_identifier);
create index map_pool_map_mode_id on sendou_ink.map_pool(map_mode_id);

create table sendou_ink.tournament_team (
  id                       serial primary key, 
  name                     text not null
                            check (char_length(name) < 51),
  checked_in               boolean not null default false,
  tournament_identifier    text not null references sendou_ink.tournament(identifier),
  -- todo restrict access
  invite_code              uuid not null unique default uuid_generate_v1mc(),
  unique (name, tournament_identifier)
);

create index tournament_team_tournament_identifier on sendou_ink.tournament_team(tournament_identifier);

create table sendou_ink.tournament_team_roster (
  member_id           integer not null references sendou_ink.account(id),
  tournament_team_id  integer not null references sendou_ink.tournament_team(id),
  captain             boolean not null default false,
  unique (member_id, tournament_team_id)
);

create index tournament_team_roster_member_id on sendou_ink.tournament_team_roster(member_id);
create index tournament_team_roster_tournament_team_id on sendou_ink.tournament_team_roster(tournament_team_id);
