classdef cadnet < handle & matlab.mixin.SetGet & matlab.mixin.Copyable & matlab.mixin.CustomDisplay
% cadnet creates a cadnet object w.r.t the cadnet name.
%
% c = cadnet(pobj,'Cadnetname') takes pcbFileRead as input and creates the
% cadnet object w.r.t. the Cadnetname.
%
% cadnet properties:
%
%   pcBoard      - pcbFileRead object.
%   CadnetName    - Name of the cadnet as an input.
%   NumPins       - Number of pins w.r.t the cadnet.
%   NumSurfaces   - Number of surfaces w.r.t the cadnet.              
%   NumVias       - Number of vias w.r.t the cadnet.
%   NumTraces     - Number of traces w.r.t the cadnet.
%   TotalLength   - Total length of the cadnet.     
%   Voltage       - voltage w.r.t the cadnet.
%   LayerRange    - Layer range that the cadnet can go through.
%   LengthOnEachLayer    - Length of traces in each layer in inch.          
%   EntityList           - Entity list w.r.t the cadnet.
%
% cadnet methods:
%   
%   shapes       - Returns the shape of the entities w.r.t the cadnet.
%   cadnetData   - Returns the object of the entities w.r.t the cadnet.
%

%   Copyright 2024 The MathWorks, Inc.

    properties(SetObservable)
        % pcbFileRead object.
        pcBoard
        % Name of the cadnet.
        CadnetName
    end
    properties(SetAccess = private, GetAccess = public)
        % Number of pins w.r.t the cadnet.
        NumPins
        % Number of Surfaces w.r.t the cadnet.
        NumSurfaces
        % Number of Vias w.r.t the cadnet.
        NumVias
        % Number of Traces w.r.t the cadnet.
        NumTraces
        % Total length of the cadnet.
        TotalLength
        % voltage w.r.t the cadnet.
        Voltage
        % Layer Range.
        LayerRange
        % Length of traces in each Layer w.r.t the cadnet.
        LengthOnEachLayer
        % Entity list w.r.t the cadnet.
        EntityList
    end


    methods
        function obj = cadnet(pcBoard,CadnetName)
            arguments
                pcBoard(1,1)  pcbFileRead
                CadnetName
            end

            obj.pcBoard = pcBoard;
            obj.CadnetName = CadnetName;
        end
    end

    methods % set/get methods
        function set.pcBoard(obj,propval)
            if ~isa(propval,'pcbFileRead')
                error(message('rfpcb:rfpcberrors:Unsupported','This input',...
                    'pcBoard. Supported input is pcbFileRead object'));
            end
            if isPropertyChanged(obj,obj.pcBoard,propval)
                obj.pcBoard =  propval;
            end
        end

        function set.CadnetName(obj,propval)
            mustBeNonempty(propval);
            if ~isempty(propval)
                if ~((ischar(propval) || isStringScalar(propval)) && strlength(propval) > 0)
                    error(message('rfpcb:rfpcberrors:PCBNameNotString','CadnetName'));
                end
                validateCadnetName(obj,propval)
                if isPropertyChanged(obj,obj.CadnetName,propval)
                    if isstring(propval)
                        propval = char(propval);
                    end
                    obj.CadnetName =  propval;
                    UpdateCadnetProp(obj);
                end
            end
        end
    
        function Csurf = get.NumSurfaces(obj)
            cadnetSurf = metalSurface(obj.pcBoard,"Cadnet",obj.CadnetName);
            if ~isempty(cadnetSurf.SurfaceInfo)
                Csurf =  max(cadnetSurf.SurfaceInfo.SurfaceIndex);
            else
                Csurf = 0;
            end
            obj.NumSurfaces = Csurf;
        end

        function Cpins = get.NumPins(obj)
            cadnetData = getCadnetData(obj.CadnetName);
            Cpins =  cadnetData.numOfPins;
            obj.NumPins = Cpins;
        end

        function Cvias = get.NumVias(obj)
            cadnetVia = vias(obj.pcBoard,"Cadnet",obj.CadnetName);
            Cvias =  cadnetVia.NumVias;
            obj.NumVias = Cvias;
        end
        
        function Ctraces = get.NumTraces(obj)
            cadnetTrace = traces(obj.pcBoard,"Cadnet",obj.CadnetName);
            Ctraces =  cadnetTrace.NumTracePath;
            obj.NumTraces = Ctraces;
        end
        function Tlen = get.TotalLength(obj)
            cadnetData = getCadnetData(obj.CadnetName);
            Tlen =  cadnetData.length;
            obj.TotalLength = Tlen;
        end

        function vol = get.Voltage(obj)
            cadnetData = getCadnetData(obj.CadnetName);
            vol = cadnetData.voltage;
            obj.Voltage = vol;
        end
        % 
        % function LayerR = get.LayerRange(obj)
        %     cadnetLayer = getCadnetLayerRange(obj);
        %     LayerR = cadnetLayer;
        %     obj.LayerRange = LayerR;
        % end

        function LayerLength = get.LengthOnEachLayer(obj)
            %cadnetData = getCadnetData(obj.CadnetName);
            LayerLength = [];
            obj.LengthOnEachLayer = LayerLength;
        end

        function Elist = get.EntityList(obj)
            % Entity list of cadnets
            Elist = GetEntityList(obj);
            obj.EntityList = Elist;
        end
    end

    methods (Hidden)
        function UpdateCadnetProp(obj)
            if ~isempty(obj.CadnetName)
                prop = get(obj);
            end
        end
    end

    methods
        function netD = cadnetData(obj,opt)
            % cadnetData returns the objects of the entities w.r.t the
            % cadnet.
            %
            % netD = cadnetData(obj) returns the objects of all the 
            % entities w.r.t the cadnet.
            %
            % netD = cadnetData(obj,Type="Surfaces") returns the object of
            % surfaces w.r.t the cadnet.
            %
            %   Input Arguments:
            %
            %       obj         : cadnet object.
            %       Type        : Type of the entity w.r.t the cadnet 
            %  
            %   Output Arguments:
            %  
            %       netD : Returns the objects of entities w.r.t the 
            %              cadnet.

            % Copyright 2024 The MathWorks, Inc.

            arguments
                obj(1,1)  cadnet
                opt.Type(1,1) {mustBeMember(opt.Type,["Surfaces","Pins","Vias","Traces"])}
            end
            tf =  fields(opt);
            p = obj.pcBoard;
            cname = obj.CadnetName;
            if isempty(tf)
                CadnetData = struct;
                CadnetData.Surfaces = metalSurface(p,'Cadnet',cname);
                CadnetData.Pins = pins(p,"Cadnet",cname);
                CadnetData.Vias = vias(p,"Cadnet",cname);
                CadnetData.Traces = traces(p,"Cadnet",cname);
            else
                type = opt.Type;
                if strcmp(type,'Surfaces')
                    CadnetData= metalSurface(p,'Cadnet',cname);
                elseif strcmp(type,'Pins')
                    CadnetData =  pins(p,"Cadnet",cname);
                elseif strcmp(type,'Vias')
                    CadnetData = vias(p,"Cadnet",cname);
                elseif strcmp(type,'Traces')
                    CadnetData= traces(p,"Cadnet",cname);
                end
            end
            netD = CadnetData;
        end

        function S = shapes(obj,opt)
            %shapes returns shapes of the entities w.r.t the cadnet.
            %
            % S = shapes(obj) returns the shapes of all the entities w.r.t
            % the cadnet.
            %
            % S = shapes(obj,'Type',"Surfaces") returns the surfaces w.r.t
            % the cadnet.
            %
            %   Input Arguments:
            %
            %       obj         : cadnet object.
            %       Type        : Type of the entity w.r.t the cadnet
            %
            %   Output Arguments:
            %
            %       S : Returns the shapes of entities w.r.t the
            %           cadnet.

         % Copyright 2024 The MathWorks, Inc.

           arguments
                obj(1,1)  cadnet
                opt.Type(1,1) {mustBeMember(opt.Type,["Surfaces","Pins","Vias","Traces"])}
            end
            tf =  fields(opt);
            pcb = obj.pcBoard;
            cname = obj.CadnetName;

            if isempty(tf)
                CadnetShape = struct;
                m = metalSurface(pcb,'Cadnet',cname);
                CadnetShape.Surfaces = shapes(m);
                p =  pins(pcb,"Cadnet",cname);
                CadnetShape.Pins = shapes(p);
                v =  vias(pcb,"Cadnet",cname);
                CadnetShape.Vias = shapes(v);
                t =  traces(pcb,"Cadnet",cname);
                CadnetShape.Traces = shapes(t);
            else
                type = opt.Type;
                if strcmp(type,'Surfaces')
                    CadnetData= metalSurface(pcb,'Cadnet',cname);
                    CadnetShape = shapes(CadnetData);
                elseif strcmp(type,'Pins')
                    CadnetData =  pins(pcb,"Cadnet",cname);
                    CadnetShape = shapes(CadnetData);
                elseif strcmp(type,'Vias')
                    CadnetData = vias(pcb,"Cadnet",cname);
                    CadnetShape = shapes(CadnetData);
                elseif strcmp(type,'Traces')
                    CadnetData= traces(pcb,"Cadnet",cname);
                    CadnetShape = shapes(CadnetData);
                end
            end
            S = CadnetShape;
        end
    end
    methods (Hidden)
        function validateCadnetName(obj,propval)
            mCnetName = cadnetList(obj.pcBoard).CadnetList;
            mustBeMember(propval,mCnetName);
        end

        % function cadnetLayerRange = getCadnetLayerRange(obj)
        %     % Get the layer range for the respecive cadnets
        %     Cname = obj.CadnetName;
        %     pfileObj = obj.pcBoard;
        %     cdata_surf = metalSurface(pfileObj,"Cadnet",Cname);
        %     % layer info of cadnet surfaces
        %     CSurfLayer = cdata_surf.SurfaceInfo.LayerNumber;
        % 
        %     % Get the cadnet pins
        %     cdata_pin = pins(pfileObj,"Cadnet",Cname);
        %     % layer info of cadnet surfaces
        %     CPinLayer = cdata_pin.PinInfo.LayerNumber;
        % 
        %     % Get the cadnet vias
        %     cdata_vias = vias(pfileObj,"Cadnet",Cname);
        %     % start layer info of cadnet via
        %     CViaStartLayer = cdata_vias.ViaInfo.StartLayerNumber;
        %     % stop layer info of cadnet via
        %     CViaStopLayer = cdata_vias.ViaInfo.StopLayerNumber;
        % 
        %     % Get the cadnet traces
        %     cdata_trace = traces(pfileObj,"Cadnet",Cname);
        %     % layer info of cadnet surfaces
        %     CTraceLayer = cdata_trace.TracePathInfo.("Layer number");
        % 
        %     % Unique layer number
        %     CnetLayer = unique([CSurfLayer;CPinLayer;CViaStartLayer;CViaStopLayer;CTraceLayer])';
        %     cadnetLayerRange = CnetLayer;
        % 
        % end
        function EntityList = GetEntityList(obj)

            % List w.r.t cadnet
            % Cadnet entities contains: Pin, Via,Traces, Surfaces

            List = struct;
            cadnetname = obj.CadnetName;

            % Get the Pins of cadnet
            pinCount = getCadnetPinsCount(cadnetname);
            Pins= struct;
            Pins.PinCount = pinCount;
            if pinCount~=0
                PinArea = 1;
                MinPinArea = num2str(min(PinArea)); MaxPinArea = num2str(max(PinArea));unit = 'sqm';
                Pins.MinPinArea = [MinPinArea,' ',unit];
                Pins.MaxPinArea = [MaxPinArea,' ',unit];
            end
            List.Pins = Pins;

            % Get the Vias of cadnet
            viaCount = getCadnetViasCount(cadnetname);
            Vias= struct;
            Vias.ViaCount = viaCount;
            if viaCount~=0
                ViaArea = 7;
                MinViaArea = num2str(min(ViaArea)); MaxViaArea = num2str(max(ViaArea));unit = 'sqm';
                Vias.MinViaArea = [MinViaArea,' ',unit];
                Vias.MaxViaArea = [MaxViaArea,' ',unit];
            end
            List.Vias = Vias;

            % Get traces of cadnet
            TraceCount = getCadnetTracePathsCount(cadnetname);
            Traces = struct;
            Traces.TraceCount = TraceCount;
            if TraceCount~=0
                TraceArea = 7;
                MinTraceArea = num2str(min(TraceArea)); MaxTraceArea = num2str(max(TraceArea));unit = 'sqm';
                Traces.MinTraceArea = [MinTraceArea,' ',unit];
                Traces.MaxTraceArea = [MaxTraceArea,' ',unit];
            end
            List.Traces = Traces;

            % Get surfaces of cadnet
            SurfaceCount = getCadnetSurfaceCount(cadnetname);
            Surf = struct;
            Surf.SurfaceCount = SurfaceCount;
            if SurfaceCount~=0
                SurfaceArea = 7;
                MinSurfaceArea = num2str(min(SurfaceArea)); MaxSurfaceArea = num2str(max(SurfaceArea));unit = 'sqm';
                Surf.MinSurfaceArea = [MinSurfaceArea,' ',unit];
                Surf.MaxSurfaceArea = [MaxSurfaceArea,' ',unit];
            end
            List.Surf = Surf;
            EntityList = List;
        end

        function tf = isPropertyChanged(~,val1,val2)
            % Check if property values are different
            if isempty(val1)        % During constructor call
                tf = true;
            else
                tf = ~isequal(val1,val2);
            end
        end
    end
end