classdef radarIOFileMex < radarIO
    %UNTITLED4 Summary of this class goes here
    %   Detailed explanation goes here
    
    properties
        %% Define constants to support acquiring data
        fd;
        Pathname;
        Filename;
    end

    methods
        function obj =radarIOFileMex(radarObj, varargin)
            % * WxMode_b -- boolean to override of the file name convention
            %   that identifies weather mode by a string with "Wx" in the
            %   filename.
            % * Filename - name of file to load, this function will prompt
            %   the operator to select a file(s) to process.
            
            obj.cipMetaData = radarObj.cipMetaData;
            obj.sourceRadar = radarObj;
            if nargin < 2
                [aFilename, aPathname]= uigetfile('*.dat*',...
                    'Select Data-Recording file(s) to process',...
                    'multiselect','on');
            else
                aFilename = varargin{1};
            end
            if (isfloat(aFilename))
                error('No files selected');
            end
            if (ischar(aFilename))
                aFilename={aFilename}; % make it always a cell array...
            end
            %   handle Weather mode options...            
            if (contains(aFilename{1},'Wx')||contains(aFilename{1},'wx')||contains(aFilename{1},'.dat_w1')||contains(aFilename{1},'.dat_w2'))
                obj.cipMetaData.wxMode=true;
            end

            if (contains(aFilename{1},'.dat_u1')||contains(aFilename{1},'.dat_w1'))
                obj.cipMetaData.fileVer=1;
            elseif (contains(aFilename(1), '.dat_u2')||contains(aFilename(1),'dat_w2'))
                obj.cipMetaData.fileVer=2;    
            end

            if (obj.cipMetaData.wxMode)
                % Wx mode differences... 120 PRIs / CIP
                radarMode=radChan.WxMode(true);
                obj.cipMetaData.numPris = obj.cipMetaData.numPrisWx;
                obj.cipMetaData.bandWidth=obj.cipMetaData.bandWidthWx;
                obj.cipMetaData.sampleRate_sps=obj.cipMetaData.sampleRateWx_sps;
                obj.cipMetaData.numChannels = obj.cipMetaData.numChannelsWx;
                obj.config.normalizerType = obj.config.normalizerType_wx;
                obj.cipMetaData.pulseLength_s = obj.cipMetaData.pulseLengthWx_s;
                obj.config.clutterCellPeak = obj.config.clutterCellPeakWx;
                obj.cipMetaData.priMarkerSize = 4;
                obj.calcWaveformParams();

            else
                radarMode=radChan.WxMode(false);
                obj.cipMetaData.numPris = obj.cipMetaData.numPrisUas;
                obj.cipMetaData.bandWidth=obj.cipMetaData.bandWidthUas;
                obj.cipMetaData.sampleRate_sps=obj.cipMetaData.sampleRateUas_sps;
                obj.config.normalizerType = obj.config.normalizerType_uas;
                obj.cipMetaData.pulseLength_s = obj.cipMetaData.pulseLengthUas_s;
                obj.config.clutterCellPeak = obj.config.clutterCellPeakUas;
                obj.cipMetaData.priMarkerSize = 16;
                obj.calcWaveformParams();
            end
            obj.readSize = (obj.cipMetaData.numPris * obj.cipMetaData.numChannels * obj.iQ * obj.cipMetaData.priSize);

            if ~exist('aPathname',"var")
                aPathname = [pwd '\'];
            end

            % read in the file...
            fprintf("Processing data record file: \n(\'%s\',\'%s\')\n", aFilename{1},aPathname);

            %PRI marker = 0000 for old file format 0x8A8A (-30070) for new
            %format
            if (obj.cipMetaData.fileVer == 2)
                priMarker = -30070;                     %0x8A8A
            else
                priMarker = 0;
            end
            % open the first file...
            %test MEX function FileData()

            %open file name

            obj.readFileName = strcat(aPathname, aFilename{1});
            %Open the file
            [~,~] = FileData(1, [], 0,  obj.readFileName);
            %fprintf("status = %d\n", status);
            %Get size of file
            [~,filesz] = FileData(6, [], 0, obj.readFileName);   %get size of file
            obj.fileSize = filesz;
            fprintf("File size = %d bytes\n", obj.fileSize);
            obj.fileSize=obj.fileSize/2;              %filesize in words
            initialReadSize = ((obj.discardPris * obj.cipMetaData.priSize)) * obj.cipMetaData.numChannels * obj.iQ;
            %fprintf(1,'discarding %d int16 words\n',initialReadSize);
            obj.filePtr = initialReadSize * 2; %byte
            [~,~] = FileData(5, [], obj.filePtr, obj.readFileName);       %set pointer into file
            %fprintf(1, "Discarded %d bytes at %d\n",obj.filePtr, currPtr);

            % do nothing with this initial data... it is just discarded
            %hds Read in  PRIs worth of data words
            pri2 =obj.priLength*2;
            %fprintf(1,"Number to collect: %d, pointer = %d\n", pri2, currPtr); %get data at pri*2
            iqData = ones(pri2, 1, 'double');
            [iqData, ~] = FileData(2, iqData, pri2, obj.readFileName);
            %find PRI marker
            filePtrIdx = find(iqData == priMarker);
            PtrPtrIdx = size(filePtrIdx, 1);    %size of index
            %if no PRI found, exit
            if(PtrPtrIdx < obj.cipMetaData.priMarkerSize)
                error("Error: PRI not found or wrong length\n");
            end

            obj.fileStartLoc = ((obj.filePtr + (filePtrIdx(1))*2)-2);           % get pointer to PRI marker in bytes Use first value in filePtrIdx

            obj.filePtr = obj.fileStartLoc;
            [~, ~] = FileData(5, [], obj.filePtr, obj.readFileName);    %Set pointer to beginning of PRI

            % figure out how large the file is in pri(s) and cips(s)...

            filesize = (obj.fileSize - obj.filePtr) * 2;      % get remaining file size in bytes
            %compute number of PRIs in file
            obj.cipMetaData.fileSizePris=floor(filesize/...
                (obj.cipMetaData.priSize*obj.cipMetaData.numChannels*obj.iQ*2));
            obj.cipMetaData.fileSizeCips=floor(filesize/(obj.readSize*2));
            videoCips=floor(obj.cipMetaData.fileSizePris/251); % todo calculate the magic number...
            %fprintf("file contains %d (%d) cips\n", obj.cipMetaData.fileSizeCips,videoCips);
            fprintf("file contains %d %1d-pulse cips (%d video cips), %1.1f sec\n", ...
                obj.cipMetaData.fileSizeCips,obj.cipMetaData.numPris,videoCips, ...
                obj.cipMetaData.priTime_s * obj.cipMetaData.fileSizePris);

            % find out the Rx/Tx start error by loading a PRI and Pulse
            % compressing it, finding the peak and determining the
            % difference from expected peak.
            obj.priReadSize=obj.cipMetaData.priSize * obj.cipMetaData.numChannels * obj.iQ;
            pri2 = (obj.cipMetaData.priSize * obj.cipMetaData.numChannels * obj.iQ);       %reshape iqdata
            iqData = ones(pri2, 1, 'double');
            % get next PRI of data from file
            if(obj.UseMexFileRead)
                [iqData, ~] = FileData(2, iqData, obj.priLength, obj.readFileName);
            else
                [iqData,~] = fread(obj.fd, obj.priLength, 'int16'); %get first PRI
            end
            iqData(iqData == -30070) = 0;
            if (obj.filePtr < obj.fileSize)
                %                     fprintf("ReadSize req: %d actual: %d\n",obj.readSize,lCount);
                cipData = reshape(iqData,obj.iQ,[]);                %reshape to 2 X 33992 double should be single?
                cipData = complex(cipData(1,:),cipData(2,:));       %convert to complex 1 X 33992 complex double
                cipData = reshape(cipData,...
                    obj.cipMetaData.numChannels,[]);                % convert to 8 X 4249 complex double

                LrPc = PulseCompressor(waveformTypes.LfmUpChirp,...
                    obj.cipMetaData.bandWidth(uint32(radChan.sumLr())),...
                    obj.cipMetaData.pulseLength_s(uint32(radChan.sumLr())),...
                    obj.cipMetaData.sampleRate_sps(uint32(radChan.sumLr())),...
                    obj.cipMetaData.priSize);

                %                 Fig1=figure("Name","Replica");
                %                 plot(real(LrPc.Replica));
                %
                % need to decimate when in weather mode....
                if (obj.cipMetaData.fileVer < 2) % no decimation required for MPDR II+
                    if obj.cipMetaData.wxMode
                        sumLr=uint32(radChan.sumLr());
                        cipData(sumLr,1:ceil(obj.cipMetaData.priSize/4),:)=...
                            cipData(sumLr,1:4:end,:);
                    end
                end

                cipData(uint32(radChan.sumLr()),:) = LrPc.compress(cipData(uint32(radChan.sumLr()),:));

                [~,peakCell]=max(abs(cipData(uint32(radChan.sumLr()),...
                    obj.cipMetaData.cells.rangeZero(uint32(radChan.sumLr())):(obj.cipMetaData.cells.rangeZero(uint32(radChan.sumLr()))+...
                    obj.cipMetaData.maxRxTxBias))));
                obj.cipMetaData.cells.rxTxBiasCorr=peakCell-1;
                fprintf("Rx/Tx Bias correction: %d\n",obj.cipMetaData.cells.rxTxBiasCorr);
                % todo: remove this...
                figure;
                plot(abs(cipData(uint32(radChan.sumLr()),:)));
                hold on;
                plot(obj.cipMetaData.cells.rangeZero(uint32(radChan.sumLr()))+peakCell-1,...
                    abs(cipData(uint32(radChan.sumLr()),obj.cipMetaData.cells.rangeZero(uint32(radChan.sumLr()))+peakCell-1)),...
                    "bo");
                hold off;

                % now that we have determined the run to run rx/tx jitter
                % recalculate the start point of the waveforms...
                obj.calcWaveformParams();
                % go back to include this Pri in the next collection set...
            end
            obj.filePtr = obj.filePtr + (obj.priReadSize*2);      %point to next PRI in file (in bytes
            if(obj.UseMexFileRead)
                [~,~] = FileData(5, [], obj.filePtr, obj.readFileName); %set file pointer to PRI location
                [~,~] = FileData(4, [], obj.readSize*2, obj.readFileName); %start CIP acquisition obj.readsize = CIP length in words.
            end

            obj.Pathname = aPathname;
            obj.Filename = aFilename{1};
            obj.cipMetaData.Filename = aFilename{1};

        end
    end
end
