# Copyright 2008-2014 Cumulus Systems Incorporated.
# All Rights Reserved.

# This file provide utility functions to parse probe specific data.

# Name of the Package.
package commonDataParsingUtil;

# It is used for strict compilation.
use strict;

# It helps in debugging.
use warnings;

# This is required for logging information.
use commonLogModule;

# This stores an instance of commonDataParsingUtil class.
my $commDataParseUtil = undef;

# --------------------------------------------------------------------------------------------------------------------------------------------------
# Sub-routines
# --------------------------------------------------------------------------------------------------------------------------------------------------
# Constructor of class commonDataParsingUtil class.
#
# @param :
#   $_[0] - [In] Class name.
#   $_[1] - [In] Base folder for logging.
#   $_[2] - [In] Probe Type like NetApp.
#   $_[3] - [In] Probe Id "192.168.20.100".
#   $_[4] - [In] Instance of commonLogModule.
#
# @return :
#   Instance of commonDataParsingUtil class.
sub getInstance {
    # This variable stores package name.
    my $class = $_[0];

    # This variable stores base folder in which we generate logs.
    my $baseFolder = $_[1];

    # This variable stores probe type.
    my $probeType = $_[2];

    # This variable stores probe id.
    my $probeId = $_[3];

    # Get commonLogModule instance.
    my $logObject = $_[4];

    # Create class instance.
    $commDataParseUtil = bless {
        probeType => $probeType,
        probeId => $probeId,
        logObj => $logObject,
        baseFolder => $baseFolder,
    }, shift unless $commDataParseUtil;

    return $commDataParseUtil;
}

# This function is used if a CLI Output comes in a format where first line contains the column names whose corresponding values will be displayed
# from next line onwards. Example:
#
# LUN   Volume   Size   Master   Serial Number   Locked
# 1     Test1    17              12              no
#
# We pass "LUN   Volume   Size   Master   Serial Number   Locked" line to this function. It finds out from which position to which position we can
# get the output value corresponding to each column. For example, in the above case for "Volume" column, it will populate the map passed as out
# parameter with 1 as key and "6, 9" as value. Here the key depicts the column number. "6" in value string depicts the starting index of Volume
# column while "9" depicts the difference of starting position of "Size" column and starting position of "Volume" column.
#
# @param :
#   $_[0] - [In] Reference to the object.
#   $_[1] - [In] Line containing the resource header information.
#   $_[2] - [Out] Map containing column number as key and the comma separated starting position and length of each column data as value.
#                 For the last column, length will be returned as "-1".
#
# @return :
#   None
sub getColumnDataPosition {
    my $line = $_[1];

    my %columnHeaderPositionHash = ();

    # Remove trailing spaces.
    $line =~ s/\s+$//;

    # Splitting line on basis of two or more spaces.
    my @positionArray = split(/ {2,}/, $line);

    my $totalElements = @positionArray;

    # Starting index of current and next column.
    my $columnStartIndex = "";
    my $nextColumnStartIndex = "";

    # Length of current column.
    my $length = "";

    # Loop for each column.
    for (my $index = 0; $index < @positionArray; $index++) {
        if ($index == ($totalElements - 1)) {
            $columnStartIndex = index($line, $positionArray[$index]);

            # Return length as "-1". Reason is that header string length and actual data length will be different so can't use header string length.
            $length = -1;
        } else {
            $columnStartIndex = index($line, $positionArray[$index]);

            $nextColumnStartIndex = index($line, $positionArray[$index + 1]);
            $length = $nextColumnStartIndex - $columnStartIndex;
        }

        # Update information about current column with start index and its length.
        $columnHeaderPositionHash{$index} = "$columnStartIndex,$length";
    }

    %{$_[2]} = %columnHeaderPositionHash;
}

# This function is used if a CLI Output comes in a format where first line contains the column names whose corresponding values will be displayed
# from next line onwards. Example:
#
# LUN   Volume   Size   Master   Serial Number   Locked
# 1     Test1    17              12              no
#
# We pass the line containing the data output like "1     Test1    17              12              no" to this function. It will use the map passed
# to it which contain column number as key and the comma separated starting position and length of each column data as value. On the basis of this
# map, it fetches the value corresponding to each required column from the input line passed to it.
#
# @param :
#   $_[0] - [In] Reference to the object.
#   $_[1] - [In] Line containing the resource output information.
#   $_[2] - [In] Map containing column number as key and the comma separated starting position and length of each column data as value.
#   $_[3] - [In] List containing the information for which column we have to get the output.
#   $_[4] - [Out] List containing the value corresponding to each column number that have been passed in the $_[3] parameter.
#
# @return :
#   None
sub getColumnDataValues {
    my $line = $_[1];

    my %columnHeaderPositionHash = %{$_[2]};

    # This array is used to store the required column numbers of a resource.
    my @columnNumberList = @{$_[3]};

    # This array is used to store the column value of each column of a resource.
    my @columnValueList = ();

    # This variable stores value corresponding to a column.
    my $columnVal = "";

    # Loop for each column whose data we need to retrieve.
    foreach (@columnNumberList) {
        # Find <start_index, data_length> information.
        my @values = split(',', $columnHeaderPositionHash{$_});

        # If length is "-1" then read till end of line.
        if (-1 == $values[1]) {
            $columnVal =  substr($line, $values[0]);
        } else {
            $columnVal =  substr($line, $values[0], $values[1]);
        }

        $columnVal =~ s/\s+$//;

        # Store the result in output list.
        push(@columnValueList, $columnVal);
    }

    @{$_[4]} = @columnValueList;
}

# The file must return true ("1") as the last statement to indicate successful execution of any initialization code. So it's customary to end such a
# file with 1 unless we are sure that we will return true otherwise. But it's better just to put the 1;, in case we add more statements.
1;