/* Table Creation */
CREATE TABLE IF NOT EXISTS "users"
(
  id bigint NOT NULL,
  username varchar NOT NULL,
  created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  deleted_at timestamp DEFAULT NULL,
  language varchar NOT NULL DEFAULT 'en-US',
  moderator boolean NOT NULL DEFAULT FALSE,
  staff boolean NOT NULL DEFAULT FALSE,
  CONSTRAINT users_id_pk PRIMARY KEY (id),
  CONSTRAINT unique_username UNIQUE (username)
);

CREATE TABLE IF NOT EXISTS "projects"
(
  id bigserial NOT NULL,
  user_id bigint REFERENCES users(id),
  remixed_from bigint DEFAULT NULL,
  version varchar NOT NULL,
  title varchar NOT NULL,
  featured boolean NOT NULL DEFAULT FALSE,
  created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  deleted_at timestamp DEFAULT NULL,
  thumbnail jsonb NOT NULL DEFAULT '{}'::JSONB,
  CONSTRAINT projects_id_pk PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS "pages"
(
  id bigserial NOT NULL,
  project_id bigint REFERENCES projects(id),
  user_id bigint REFERENCES users(id),
  x integer NOT NULL,
  y integer NOT NULL,
  created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  deleted_at timestamp DEFAULT NULL,
  styles jsonb NOT NULL DEFAULT '{}'::JSONB,
  CONSTRAINT pages_id_pk PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS "elements"
(
  id bigserial NOT NULL,
  type varchar NOT NULL,
  page_id bigint REFERENCES pages(id),
  user_id bigint REFERENCES users(id),
  created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  deleted_at timestamp DEFAULT NULL,
  attributes jsonb NOT NULL DEFAULT '{}'::JSONB,
  styles jsonb NOT NULL DEFAULT '{}'::JSONB,
  CONSTRAINT elements_id_pk PRIMARY KEY (id)
);

/* Indexes */
CREATE UNIQUE INDEX pages_xyid_unique_idx ON pages (project_id, x, y) WHERE (deleted_at IS NULL);
CREATE INDEX user_idx_id_deleted_at ON users (id, deleted_at);
CREATE INDEX project_deleted_at_user_id on projects (deleted_at, user_id);
CREATE INDEX deleted_at_remixed_from_idx on projects (deleted_at, remixed_from);
CREATE INDEX deleted_at_featured_idx on projects (deleted_at, featured);
CREATE INDEX project_id_deleted_at_idx ON pages (project_id, deleted_at);
CREATE INDEX deleted_at_page_id_idx ON elements (deleted_at, page_id);

/* Triggers */
CREATE OR REPLACE FUNCTION update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = now();
  RETURN NEW;
END;
$$ language 'plpgsql';

CREATE TRIGGER update_user_updated_at BEFORE UPDATE ON users
FOR EACH ROW EXECUTE PROCEDURE update_updated_at();

CREATE TRIGGER update_project_updated_at BEFORE UPDATE ON projects
FOR EACH ROW EXECUTE PROCEDURE update_updated_at();

CREATE TRIGGER update_page_updated_at BEFORE UPDATE ON pages
FOR EACH ROW EXECUTE PROCEDURE update_updated_at();

CREATE TRIGGER update_element_updated_at BEFORE UPDATE ON elements
FOR EACH ROW EXECUTE PROCEDURE update_updated_at();
