classdef pinsData < handle & matlab.mixin.CustomDisplay & matlab.mixin.SetGet & matlab.mixin.Copyable
% pinsData creates a pinsData object of a pin w.r.t the pin index.
%
% pdata = pinsData(sobj,PinInd) creates a pin data object of a pins w.r.t 
% the pin index.
%
% pinsData input arguments:
%   pobj            - pins object.
%   PinInd          - Index of the pin w.r.t the pin index. It accepts the
%                     scalar value.
%
% pinsData properties:
%   PinType        - Number of antipads in a surface.
%   PartNumber     - Part number of the respective pin.
%   Component      - Component name of the respective pin.
%   PinNumber      - Pin number in the component of the respective pin.
%   Value          - Value of the component.
%   PadStack       - PadStack name of the respective
%   StartLayer     - Start layer of the pin.
%
% If PinType is 'Rectangle'
%   Center            - Center of the rectangular pin in inch.
%   Length            - Length of the rectangular pin in inch.
%   Width             - Width of the rectangular pin in inch.
%
% If PinType is 'Circle'
%   Center      - Center of the circular antipads in meter.
%   HoleDiameter          - Diameter of the circular antipads in meter
%   Diameter
%
% surfaceAntipad methods:   
%   shapes  - Returns the shape of the pin w.r.t the pin index

% Copyright 2023 The MathWorks, Inc.


    properties(SetAccess = private, GetAccess = public)
        % Pin or shape of the pin
        PinType
        % Part Name
        PartNumber
        % Component name
        Component
        % Pin Number
        PinNumber
        % Component value
        Value
        % Padstack name
        PadStack
        % StartLayer 
        StartLayer
        % Stop Layer
        StopLayer
        % Pin Rectangle
        % Center of the rectangle/circular pin in meter
        Center
        % Length of the rectangle in meter
        Length
        % Width of the rectangle in meter
        Width
        % Pin Circle
        % Drill hole diameter of pin in meter. If the pad is via pad.
        % HoleDiameter
        % Pad diameter of pin in meter
        Diameter   
        % Cadnet
        CadnetName
    end

    properties(Access=private)
        PrivatePinInd
        PrivateLayerNumber
        PrivateCadnetName
        PrivateInputType
        PrivatePinObj
    end

    methods
        function obj = pinsData(Pobj,pinInd)
            arguments
                Pobj(1,1)  pins
                pinInd(1,:) {mustBeNumeric,...
                    mustBeNonNan,mustBeFinite,mustBeInteger,...
                    mustBePositive,mustBeValidNumber(Pobj,pinInd)} = Pobj.PinInfo.PinIndex(1);
            end
            obj.PrivatePinObj = Pobj;
            obj.PrivateInputType = Pobj.InputType;
            if strcmpi(Pobj.InputType,'Layer')
                obj.PrivateLayerNumber = Pobj.LayerNumber;
            elseif strcmpi(Pobj.InputType,'Cadnet')
                obj.PrivateCadnetName = Pobj.CadnetName;
            end
            obj.PrivatePinInd = pinInd;
        end
    end
    methods %-------Set/Get-------- %
      
        function SPinType = get.PinType(obj)
            pdata = PCBDataPin(obj);
            tf = pdata.IsRectangle;
            if tf
                SPinType = 'Rectangle';
            else
                SPinType = 'Circle';
            end
        end

        function PinCen = get.Center(obj)
            pdata = PCBDataPin(obj);
            tf = pdata.IsRectangle;
            if tf
                PinCen = pdata.CenterRec;
            else
                PinCen = pdata.CenterCircle;
            end
            obj.Center = PinCen;
        end

         function PinRecLen = get.Length(obj)
            pdata = PCBDataPin(obj);
            tf = pdata.IsRectangle;
            if tf
                PinRecLen = pdata.Length;
            else
                PinRecLen = [];
            end
            obj.Length = PinRecLen;
        end

        function PinRecWid = get.Width(obj)
            pdata = PCBDataPin(obj);
            tf = pdata.IsRectangle;
            if tf
                PinRecWid = pdata.Width;
            else
                PinRecWid = [];
            end
            obj.Width = PinRecWid;
        end

        function PinDia = get.Diameter(obj)
            pdata = PCBDataPin(obj);
            tf = pdata.IsRectangle;
            if tf
                PinDia = [];
            else
                PinDia = pdata.Diameter;
            end
            obj.Diameter = PinDia;
        end

        function PinComp = get.Component(obj)
            pdata = PCBDataPin(obj);
            PinComp = pdata.Component;
            obj.Component = PinComp;
        end

        function PinNum = get.PinNumber(obj)
            pdata = PCBDataPin(obj);
            PinNum = pdata.pinNumber;
            obj.PinNumber = PinNum;
        end

         function pinV = get.Value(obj)
             pdata = PCBDataPin(obj);
             pinV = pdata.value;
             obj.Value = pinV;
         end

         function parN = get.PartNumber(obj)
             pdata = PCBDataPin(obj);
             parN = pdata.PartNumber;
             obj.PartNumber = parN;
         end

         function padS = get.PadStack(obj)
             pdata = PCBDataPin(obj);
             padS = pdata.Padstack;
             obj.PartNumber = padS;
         end

         function CadnetN = get.CadnetName(obj)
             pdata = PCBDataPin(obj);
             CadnetN = pdata.CadnetName;
             obj.CadnetName = CadnetN;
         end

         function pinL = get.StartLayer(obj)
             pdata = PCBDataPin(obj);
             pinL = pdata.StartLayer;
             obj.StartLayer = pinL;
         end

         function pinL = get.StopLayer(obj)
             pdata = PCBDataPin(obj);
             pinL = pdata.StopLayer;
             obj.StopLayer = pinL;
         end
    end

    methods (Hidden)

        function Pin = PCBDataPin(obj)
            
            pinIdx = obj.PrivatePinInd;
            if strcmpi(obj.PrivateInputType,'Layer')
                 LayerN = obj.PrivateLayerNumber;
                 pdata = getLayerPinData(int32(LayerN),int32(pinIdx));
                 Pin.CadnetName = pdata.cadnetName;
            elseif strcmpi(obj.PrivateInputType,'Cadnet')
                Cname = obj.PrivateCadnetName;
                pdata = getCadnetPinData(Cname,int32(pinIdx));
                Pin.StartLayer = pdata.startLayerNumber;
                Pin.StopLayer = pdata.endLayerNumber;
            end     
            %Pin = struct;
            % CSV definition of circular pin: If height value is zero than 
            % its a circular pin and Width is the diameter 
            height = pdata.height;
            Pin.PartNumber = pdata.partNumberName;
            Pin.Component = pdata.refdesName;
            Pin.pinNumber = pdata.pinNumber;
            Pin.value = pdata.value;
            Pin.Padstack  = pdata.padstackName;
            % Rectangular pin 
            if height~=0
                Pin.IsRectangle = 1;
                Pin.Length = pdata.width;
                Pin.Width = pdata.height;
                Pin.CenterRec = [pdata.xPosition,pdata.yPosition];
            else
                Pin.IsRectangle = 0; 
                Pin.Diameter = pdata.width;
                Pin.CenterCircle = [pdata.xPosition,pdata.yPosition];
            end
        end
    end

    methods
        function S = shapes(obj)
            %shapes returns the shape of the pins polygon in a surfaces
            %
            % S = shapes(obj) returns the shapes of pins in a surfaces
            %

            % Copyright 2023 The MathWorks, Inc.

            PinObj =  obj.PrivatePinObj;
            PinId = obj.PrivatePinInd;
            poly = createGeometry(PinObj);
            if ~isempty(poly)
                S = poly(PinId);
            else
                S = [];
            end

        end
    end

    methods (Access=protected)
        function group = getPropertyGroups(obj)
            % Full "show details" form of command-line display

            % PinDataRectangle
            % PinDataCircle

            % INITIAL / uncategorized
            %group = matlab.mixin.util.PropertyGroup(s,'');
            if strcmpi(obj.PrivateInputType,'Cadnet')
                title = ['Pin data of ', num2str(obj.PrivateInputType) ':',  obj.PrivateCadnetName];

                if matlab.internal.display.isHot
                    title = "<strong>" + title + "</strong>";
                end

                plist = {'PinType','PartNumber','Component','PinNumber','Value','PadStack','StartLayer','StopLayer'};

            elseif strcmpi(obj.PrivateInputType,'Layer')
                title = ['Pin data of ', num2str(obj.PrivateInputType) ':',  num2str(obj.PrivateLayerNumber)];

                if matlab.internal.display.isHot
                    title = "<strong>" + title + "</strong>";
                end

                plist = {'PinType','PartNumber','Component','PinNumber','Value','PadStack','CadnetName'};  
            end
            group = matlab.mixin.util.PropertyGroup(plist,title);

            if strcmpi(obj.PinType,'Rectangle')
                plist = {'Center','Length','Width'};
                title1 = 'Rectangular pin dimensions:';
                % if matlab.internal.display.isHot
                %     title1 = "<strong>" + title1 + "</strong>";
                % end
                group(end+1) = matlab.mixin.util.PropertyGroup(plist,title1);
            else
                title2 = 'Circular pin dimensions:';
                % if matlab.internal.display.isHot
                %     title2 = "<strong>" + title2 + "</strong>";
                % end
                plist = {'Center','Diameter'};
                group(end+1) = matlab.mixin.util.PropertyGroup(plist,title2);
            end
        end

        % function props = getObjectProperties(obj)
        %     G = getPropertyGroups(obj);
        %     props = fields(G.PropertyList);
        % end

    end
end
function mustBeValidNumber(PinObj,value)
PinInd = value;
PinIndExp = PinObj.PinInfo.PinIndex;
if any(PinInd==PinIndExp)
    value = value;  %#ok<ASGSL>
else
    eid = 'Value:notValid';
    msg = ['Value in PinIndex must be among the PinIndex of pin, expected value/s are: ', num2str(PinIndExp')];
    throwAsCaller(MException(eid,msg));
end
end