//----------------------------------------------------------------------
//  IMPLEMENTATION FILE (pbxcallt.cpp)
//  This module exports facilities for controlling
//  telephone calls made locally within the PBX
//----------------------------------------------------------------------
// NOTE : This version is modified for testing in the
//        following ways:
//          1) MAX_LINES is 9, not 200
//          2) a Dump function is added
//          3) the SortLines function, presented after
//             the original module, is included

#include "pbxcallt.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;
    }
}

//** CHANGE **
void SwapLines( OneLine&, OneLine& );

void PbxType::SortLines()
    //..................................................................
    // PRE:  Assigned( line[0..MAX_LINES-1] )
    // POST: line[0..MAX_LINES-1] contain same values as at invocation
    //       but are rearranged into ascending order on the "source"
    //       member.
    //       (Unused elements are located at the end of the array)
    //..................................................................
{
    int minIndx;    // Index of array element with smallest source
                    //     member in each pass
    int top;        // "False top" of array for each pass
    int j;

    for (top = 0; top < MAX_LINES-1; top++) {
                    // INV (prior to test):
                    //     line[0..top-1] are in ascending order
                    //  && All in-use elements of line[top..MAX_LINES-1]
                    //         are >= line[top-1] (by source member)
                    //  && top <= MAX_LINES-1
        minIndx = top;
        for (j = top+1; j < MAX_LINES; j++)
                        // INV (prior to test):
                        //     line[minIndx].source <= the source member
                        //       of all in-use elements of line[top..j-1]
                        //  && j <= MAX_LINES

            if (line[j].inUse && ( !line[minIndx].inUse ||
                                 line[j].source < line[minIndx].source))
                minIndx = j;

        // ASSERT: line[minIndx].source is <= the source member of all
        //           in-use elements of line[top..MAX_LINES-1]
        //      OR None of line[top..MAX_LINES-1] are in use

        if (line[minIndx].inUse)
            SwapLines(line[top],line[minIndx]);
        else
            return;     // Remaining lines are not in use
    }
}

void SwapLines( /* inout */ OneLine& line1,
                /* inout */ OneLine& line2 )
    //..................................................................
    // PRE:  Assigned(line1)  &&  Assigned(line2)
    // POST: line1==line2<entry>  &&  line2==line1<entry>
    //..................................................................
{
    OneLine temp;

    temp = line1;
    line1 = line2;
    line2 = temp;
}

//** CHANGE **
#include <iostream.h>

void PbxType::Dump() const
{
    int i;

    cout << "\n\n<<<<<<<<<<<<< DUMP >>>>>>>>>>>>>\n";
    for (i = 0; i < 1000*MAX_PREFIX; i++)
        if (phoneInUse[i])
            cout << "   Phone No. " << i+1000 << " in use. \n";
    cout << "\nStatus of phone lines:\n";
    for (i = 0; i < MAX_LINES; i++) {
        cout << "   Line No. " << i;
        if (line[i].inUse)
            cout << "   FROM: " << line[i].source+1000
                 << "   TO: " << line[i].receiver+1000
                 << "   TIME: " << line[i].time;
        cout << '\n';
    }
}


