//----------------------------------------------------------------------
//  IMPLEMENTATION FILE (pbxcalls.cpp)
//  This module exports facilities for controlling
//  telephone calls made locally within the PBX
//----------------------------------------------------------------------
#include "pbxcalls.h"

// Constant MAX_LINES is the maximum number of
// simultaneous calls
//
// Private members of class:
//    Boolean phoneInUse[1000*MAX_PREFIX];
//    OneLine line[MAX_LINES];

PbxType::PbxType()
    //..................................................................
    // Constructor
    // POST: phoneInUse[0..1000*MAX_PREFIX-1] == FALSE
    //    && line[0..MAX_LINES-1].inUse == FALSE
    //..................................................................
{
    int i;

    for (i = 0; i < 1000*MAX_PREFIX; i++)
        phoneInUse[i] = FALSE;
    for (i = 0; i < MAX_LINES; i++)
        line[i].inUse = FALSE;
}

void PbxType::Dial( /* in */  PhoneNumType caller,
                    /* in */  PhoneNumType called,
                    /* in */  TimeType     startTime,
                    /* out */ Boolean&     busy      )
    //..................................................................
    // PRE:  caller and called are in PhoneNumType range
    //    && Assigned(startTime)
    // POST: busy == TRUE, if all line[0..MAX_LINES-1].inUse == TRUE
    //                        || phoneInUse[caller-1000]<entry>
    //                        || phoneInUse[called-1000]<entry>
    //            == FALSE, otherwise
    //    && NOT busy -->  There is some j, (0 <= j < MAX_LINES),
    //                  && NOT line[j].inUse<entry>
    //                  && line[j].inUse
    //                  && line[j].source == caller-1000
    //                  && line[j].receiver == called-1000
    //                  && line[j].time == startTime
    //                  && phoneInUse[caller-1000]
    //                  && phoneInUse[called-1000]
    //..................................................................
{
    caller -= 1000;
    called -= 1000;
    if (phoneInUse[caller] || phoneInUse[called]) {
        busy = TRUE;
        return;
    }
    // ASSERT: Neither phone is in use

    int lineNum = 0;
    while (lineNum < MAX_LINES && line[lineNum].inUse)
                              // INV (prior to test):
                              //     lineNum <= MAX_LINES
                              //  && line[0..lineNum-1].inUse == TRUE
        lineNum++;

    if (lineNum >= MAX_LINES)
        // ASSERT: No line available
        busy = TRUE;
    else {
        // ASSERT: A line is available
        busy = FALSE;
        line[lineNum].inUse = TRUE;
        line[lineNum].source = caller;
        line[lineNum].receiver = called;
        line[lineNum].time = startTime;
        phoneInUse[caller] = phoneInUse[called] = TRUE;
    }
}

void PbxType::HangUp( /* in */ PhoneNumType caller,
                      /* in */ TimeType     endTime )
    //..................................................................
    // PRE:  caller is in PhoneNumType range  &&  Assigned(endTime)
    // POST: IF there is some line j, (0 <= j < MAX_LINES),
    //         && line[j].inUse<entry>
    //         && (line[j].source == caller-1000
    //             || line[j].receiver == caller-1000)
    //       THEN
    //             NOT line[j].inUse
    //          && NOT phoneInUse[line[j].receiver]
    //          && NOT phoneInUse[line[j].source]
    // NOTE: endTime is intended for future use only
    //..................................................................
{
    caller -= 1000;
    int lineNum = 0;
    while (lineNum < MAX_LINES &&
           ( !line[lineNum].inUse || (line[lineNum].source != caller &&
                                      line[lineNum].receiver != caller)))

                            // INV (prior to test):
                            //    lineNum <= MAX_LINES
                            // && For all j < lineNum, NOT line[j].inUse
                            //       || (   line[j].source != caller
                            //           && line[j].receiver != caller)
        lineNum++;

    if (lineNum < MAX_LINES) {
        line[lineNum].inUse  = FALSE;
        phoneInUse[line[lineNum].source] = FALSE;
        phoneInUse[line[lineNum].receiver] = FALSE;
    }
}


