-- logout one user ($2) from one phone ($1)
CREATE OR REPLACE FUNCTION dologoutuser(integer, integer) RETURNS integer AS '
  DECLARE
    phonereboot varchar;
    ch record; -- channel
  BEGIN
    -- should phones be rebooted? Normally yes.
    SELECT INTO phonereboot value FROM astglobals WHERE name = ''phonereboot'';

    UPDATE channel SET inuse = ''no'' WHERE phone = $1;
    UPDATE channel SET inuse = ''yes'' WHERE phone = $1 AND line = ''1'';

    RAISE NOTICE ''user % logged out from phone %'', $2, $1;
    INSERT INTO history (created, creator, contact, type, lookup, lookupid, value) VALUES
      (CURRENT_TIMESTAMP, $2, $2, ''update'', ''phone'', $1, ''logged off'');

    INSERT INTO activate(action, type, which, status, created) VALUES
      (''modify'', ''phone'', $1, ''QUEUED'', CURRENT_TIMESTAMP);

    FOR ch IN SELECT id FROM channel WHERE phone = $1 LOOP
      INSERT INTO activate(action, type, which, status, created) VALUES
        (''modify'', ''channel'', ch.id, ''QUEUED'', CURRENT_TIMESTAMP);
    END LOOP;

    IF phonereboot = ''yes'' THEN
      INSERT INTO activate(action, type, which, status, created) VALUES
        (''module'', ''phone-check-sync'', $1, ''QUEUED'', CURRENT_TIMESTAMP);
    END IF;

    RETURN ''1'';
  END;
' LANGUAGE plpgsql;

-- logout whoever is logged in on a given phone ($1)
-- also log him out on a paired phone
-- logoutuser(phone)
CREATE OR REPLACE FUNCTION logoutuser(integer) RETURNS integer AS '
  DECLARE
    _canlogout varchar;
    contactid integer;
    _phoneid integer;
    pw integer;
    pcontact integer;
    pevent integer;
    worktime integer;
  BEGIN
    _phoneid := $1;
    SELECT INTO pw pairedwith FROM phone WHERE id = _phoneid;

    -- who is currently logged in to this phone?
    SELECT INTO contactid, _canlogout id, canlogout
      FROM contact WHERE phone = _phoneid AND status <> ''deleted'' LIMIT 1;

    IF NOT FOUND OR contactid <= 1 THEN
      -- See if someone is logged in on the paired phone.
      RAISE NOTICE ''nobody logged in on phone %'', _phoneid;
      IF pw > 1 AND pw <> _phoneid THEN
        SELECT INTO contactid, _canlogout id, canlogout
          FROM contact WHERE phone = pw AND status <> ''deleted'' LIMIT 1;

        IF NOT FOUND OR contactid <= 1 THEN
          RAISE NOTICE ''nobody logged in on phone %'', pw;
          RETURN ''1'';
        ELSE
          _phoneid := pw;
          pw := $1;
        END IF;
      END IF;
    END IF;

    IF _canlogout <> ''yes'' THEN
      RAISE NOTICE ''user % cannot logout'', contactid;
      RETURN ''0'';
    END IF;

    SELECT INTO pevent, worktime event, cast(extract(epoch FROM CURRENT_TIMESTAMP - stamp) as integer)
      FROM contacthist WHERE contact = contactid AND event IN (''40'', ''41'') ORDER BY stamp DESC LIMIT 1;
    IF pevent = ''40'' THEN
      INSERT INTO contacthist (contact, stamp, event, int2, parm1) VALUES
        (contactid, CURRENT_TIMESTAMP, ''41'', worktime, ''Logoff'');
    END IF;

    UPDATE contact SET phone = 1 WHERE phone = _phoneid;
    INSERT INTO activate(action, type, which, status, created)
      VALUES (''modify'', ''contact'', contactid, ''QUEUED'', CURRENT_TIMESTAMP);

    PERFORM dologoutuser(_phoneid, contactid);

    IF pw > 1 AND pw <> _phoneid THEN
      -- Is anyone else logged in to the paired phone?
      -- This should not happen.
      SELECT INTO pcontact, _canlogout id, canlogout
        FROM contact WHERE phone = pw AND status <> ''deleted'' LIMIT 1;
      IF FOUND AND pcontact > 1 AND pcontact <> contactid THEN
        RAISE NOTICE ''ERROR: another user % logged in on paired phone %'', pcontact, pw;
        -- Should we log him out?
      ELSE
        PERFORM dologoutuser(pw, contactid);
      END IF;
    END IF;

    return ''1'';
  END;
' LANGUAGE plpgsql;

-- Set new phone, set the active channels on that phone,
-- insert activate record to recreate the provisioning files,
-- and finally reboot the phone
-- dologinuser(phone, user)
CREATE OR REPLACE FUNCTION dologinuser(integer, integer) RETURNS integer AS '
  DECLARE
    phonereboot varchar;
    pl record; -- phoneline
    ch record; -- channel
    query varchar;
    usecount integer;
  BEGIN
    -- give this phone as much channels as the user has extensions
    UPDATE channel SET inuse = ''no'' WHERE phone = $1;
    FOR pl IN SELECT line FROM phoneline WHERE function = ''contact'' AND lookupid = $2 AND status <> ''deleted'' LOOP
      query := ''UPDATE channel SET inuse = '' || quote_literal(''yes'') ||
               '' WHERE phone = '' || quote_literal($1) || '' AND line = '' || quote_literal(pl.line);
      -- raise notice ''query: %'', query;
      EXECUTE query;
    END LOOP;

    -- ensure that at least one channel is enabled, some phones refuse to start up without channels
    SELECT INTO usecount COUNT(*) FROM channel WHERE phone = $1 AND inuse = ''yes'';
    IF usecount < 1 THEN
      UPDATE channel SET inuse = ''yes'' WHERE phone = $1 AND line = ''1'';
    END IF;

    RAISE NOTICE ''user % logged in to phone %'', $2, $1;
    INSERT INTO activate(action, type, which, status, created) VALUES
      (''modify'', ''phone'', $1, ''QUEUED'', CURRENT_TIMESTAMP);
    INSERT INTO history (created, creator, contact, type, lookup, lookupid, value) VALUES
      (CURRENT_TIMESTAMP, $2, $2, ''update'', ''phone'', $1, ''logged on'');
    INSERT INTO activate(action, type, which, status, created) VALUES
      (''modify'', ''contact'', $2, ''QUEUED'', CURRENT_TIMESTAMP);
    FOR ch IN SELECT id FROM channel WHERE phone = $1 LOOP
      INSERT INTO activate(action, type, which, status, created) VALUES
        (''modify'', ''channel'', ch.id, ''QUEUED'', CURRENT_TIMESTAMP);
    END LOOP;

    -- should phones be rebooted? Normally yes.
    SELECT INTO phonereboot value FROM astglobals WHERE name = ''phonereboot'';

    IF phonereboot = ''yes'' THEN
      INSERT INTO activate(action, type, which, status, created) VALUES
        (''module'', ''phone-check-sync'', $1, ''QUEUED'', CURRENT_TIMESTAMP);
    END IF;

  RETURN ''1'';
  END;
' LANGUAGE plpgsql;

-- login a user to a phone, returns the previous phone
-- If this user is logged in on another phone, log him out, if possible.
-- If someone else is logged in to this phone (or the phone paired with it), log him out, if possible.
-- loginuser(phone, user)
CREATE OR REPLACE FUNCTION loginuser(integer, integer) RETURNS integer AS '
  DECLARE
    prevphone integer;
    pw integer;
    comp integer; -- company
    need_lic_check varchar; -- need license checking?
    _lic_per_company varchar; -- count per company licences?
    _lic_used integer; -- current amount of used licenses
    _licenses integer; -- assigned amount of used licenses
    curuser integer; -- current logged in user on this phone
    _canlogout varchar;
  BEGIN
    IF $1 <= 1 OR $2 <= 1 THEN
      RAISE NOTICE ''ERROR: invalid arguments to loginuser'';
      RETURN ''0'';
    END IF;

    need_lic_check := ''yes'';

    -- get the previous phone this user was logged in to
    SELECT INTO prevphone, _canlogout phone, canlogout FROM contact WHERE id = $2;

    IF prevphone = $1 THEN
      RAISE NOTICE ''user % already logged in on %'', $2, $1;
      RETURN prevphone;
    END IF;

    -- get id of phone, this phone is paired with
    SELECT INTO pw pairedwith FROM phone WHERE id = $1;
    IF pw > 1 AND prevphone = pw THEN
      RAISE NOTICE ''user % already logged in on %'', $2, pw;
      RETURN prevphone;
    END IF;

    IF prevphone > 1 AND _canlogout <> ''yes'' THEN
      RAISE NOTICE ''% logged in on another phone and cannot logout'', $2;
      RETURN ''0'';
    END IF;

    -- Is anyone else logged into this phone?
    SELECT INTO curuser, _canlogout id, canlogout FROM contact WHERE phone = $1 AND status <> ''deleted'';
    IF FOUND AND curuser > 1 THEN
      IF _canlogout <> ''yes'' THEN
        RAISE NOTICE ''% logged in on this phone % and cannot logout'', curuser, $1;
        RETURN ''0'';
      END IF;

      PERFORM logoutuser($1);
      need_lic_check := ''no'';
    END IF;

    -- Is anyone else logged into the paired phone?
    IF pw > 1 THEN
      SELECT INTO curuser, _canlogout id, canlogout FROM contact WHERE phone = pw AND status <> ''deleted'';
      IF FOUND AND curuser > 1 THEN
        IF _canlogout <> ''yes'' THEN
          RAISE NOTICE ''% logged in on phone % and cannot logout'', curuser, pw;
          RETURN ''0'';
        END IF;

        PERFORM logoutuser(pw);
        need_lic_check := ''no'';
      END IF;
    END IF;

    -- if switching to another phone, logout of the previous phone
    IF prevphone <> 1 THEN
      PERFORM logoutuser(prevphone);
      need_lic_check := ''no'';
    END IF;

    -- check license count
    SELECT INTO comp company FROM contact WHERE id = $2;
    IF need_lic_check = ''yes'' THEN
      RAISE NOTICE ''Need licenses check company %'', comp;
      SELECT INTO _lic_per_company value FROM astglobals WHERE name = ''lic_per_company'';
      -- are licenses set per company?
      IF _lic_per_company = ''yes'' THEN
        RAISE NOTICE ''licenses set per company'';
        SELECT INTO _licenses licenses FROM company where id = comp;
        SELECT INTO _lic_used count(*) as count FROM contact LEFT JOIN phone ON phone.id = contact.phone
          WHERE contact.phone > 1 AND contact.status != ''deleted'' AND phone.phonetype != 160 AND contact.company = comp;
        RAISE NOTICE ''used = %, max = %'', _lic_used, _licenses;
        IF _lic_used >= _licenses THEN
          RAISE NOTICE ''% cannot login: max licenses for company % = %'', $2, comp, _licenses;
          RETURN ''-1'';
        END IF;
      END IF;
      SELECT INTO _licenses value FROM astglobals WHERE name = ''licusers'';
      SELECT INTO _lic_used count(*) as count FROM contact LEFT JOIN phone on phone.id = contact.phone 
        WHERE contact.phone > 1 and contact.status != ''deleted'' and phone.phonetype != 160;
      IF _lic_used >= _licenses THEN
        RAISE NOTICE ''% cannot login: max licenses for system = %'', $2, _licenses;
        RETURN ''-1'';
      END IF;
    END IF;

    INSERT INTO contacthist (contact, stamp, event, parm1) VALUES
      ($2, CURRENT_TIMESTAMP, ''40'', ''Logon'');

    UPDATE contact SET phone = $1 WHERE id = $2;

    PERFORM dologinuser($1, $2);

    IF pw > 1 THEN
      PERFORM dologinuser(pw, $2);
    END IF;

    RETURN prevphone;
  END;
' LANGUAGE plpgsql;

