classdef surfaceVia < handle
% surfaceVia creates a surfaceVia object that returns the data of the 
% surface vias
%
% S = surfaceVia(sobj,SurfInd) creates a via object of a metalSurface w.r.t
% the surface index.
%
% surfaceVia input arguments:
%   sobj            - metalSurface object.
%   SurfInd         - Index of the surface in a metalSurface. It accepts the
%                     scalar value.
%
% surfaceVia properties:
%   NumVias           - Number of vias in a surface.
%   Shape             - Shape of the Vias in a surfaces.
%   Center            - Center of the via in meter.
%   DrillHoleDiameter - Drill hole diameter of via in meter.
%   
% surfaceVia methods:  
%   shapes  - Returns the shape of the vias in a surface

% Copyright 2023 The MathWorks, Inc.

    properties(SetAccess = private, GetAccess = public)
        % Number of vias
        NumVias
        % Shape of the vias
        % Shape
        % Center of the via in meter
        Center
        % Drill hole diameter of the via in meter
        DrillHoleDiameter
    end

    properties(Access=private)
        PrivateSurfaceInd
        PrivateLayerNumber
        PrivateCadnetName
        PrivateInputType
    end

    methods
        function obj = surfaceVia(Sobj,SurfInd)
            arguments
                Sobj(1,1)  metalSurface
                SurfInd(1,1) {mustBeNumeric,...
                    mustBeNonNan,mustBeFinite,mustBeInteger,...
                    mustBePositive,mustBeValidNumber(Sobj,SurfInd)};
            end
            obj.PrivateInputType = Sobj.InputType;
            if strcmpi( obj.PrivateInputType,'Layer')
                obj.PrivateLayerNumber = Sobj.LayerNumber;
            elseif strcmpi( obj.PrivateInputType,'Cadnet')
                obj.PrivateCadnetName = Sobj.CadnetName;
            end
            obj.PrivateSurfaceInd = SurfInd;
        end
    end
    methods %-------Set/Get-------- %
        function ViaCnt = get.NumVias(obj)
            [ViaCnt, ~, ~] = getViadata(obj);
            obj.NumVias =  ViaCnt;
        end

        % function Shape = get.Shape(obj)
        %     Shape = CreateSurfaceVia(obj,obj.PrivateSurfaceInd);
        %     obj.Shape =  Shape;
        % end

        function ViaLoc = get.Center(obj)
            [~, ViaLoc, ~] = getViadata(obj);
            obj.Center =  ViaLoc;
        end

        function ViaDia = get.DrillHoleDiameter(obj)
            [~, ~, ViaDia] = getViadata(obj);
            obj.DrillHoleDiameter =  ViaDia;
        end
    end

    methods (Hidden)
        function [count, location, HoleDia] = getViadata(obj)
            
            Sidx = obj.PrivateSurfaceInd;
            if ~isempty(obj.PrivateLayerNumber)
                Lid = obj.PrivateLayerNumber;
                Surf_LayerId = getLayerSurfaceId(int32(Lid));
            else
                Surf_LayerId = getCadnetSurfaceIndexList(obj.PrivateCadnetName)';
            end

            ViaCnt = getSurfaceViaCount(int32(Surf_LayerId(Sidx)));
            count = ViaCnt;
            viaCount = ViaCnt;
            if ~(viaCount==0)
                viaData = zeros(viaCount,3);
                viaLoc = zeros(viaCount,2);
                viaDia = zeros(viaCount,1);
                for viaIdx = 1 : viaCount
                    via(viaIdx) = getSurfaceViaData(int32(Surf_LayerId(Sidx)), int32(viaIdx));
                    viaData(viaIdx,:) =  [via(viaIdx).xCoord,via(viaIdx).yCoord,via(viaIdx).holeDia];
                    viaLoc(viaIdx,:) =  [via(viaIdx).xCoord,via(viaIdx).yCoord];
                    viaDia(viaIdx,:) =  [via(viaIdx).holeDia];
                end
                location = viaLoc;
                HoleDia = viaDia;
            else
                location = [];
                HoleDia = [];
            end
        end

        function SurfViaPoly = CreateSurfaceVia(obj,surfInd)
            % This function is used to create the via polygon

            % Get the Actual surface ID w.r.t layer
            if ~isempty(obj.PrivateLayerNumber)
                Lid = obj.PrivateLayerNumber;
                Surf_LayerId = getLayerSurfaceId(int32(Lid))';
            else
                Surf_LayerId = getCadnetSurfaceIndexList(obj.PrivateCadnetName)';
            end
            surfIdx = Surf_LayerId(surfInd);

            % Get the via hole count
            viaCount = getSurfaceViaCount(int32(surfIdx));          
            if ~(viaCount == 0)
                orig_state = warning;
                warning('off','MATLAB:polyshape:repairedBySimplify');
                viaIdx = 1: viaCount;
                % RHolePoly = arrayfun(@(x) CreateRHVertices(obj,surfIdx,x),rhIdx);
                % RHolePoly = union(RHolePoly);
                % SurfRHPoly = antenna.Polygon('Vertices',RHolePoly.Vertices)

                ViaVertices = arrayfun(@(x) CreateViaVertices(obj,surfIdx,x),viaIdx,'UniformOutput',false);
                ViaPolyV =  cell2mat(ViaVertices');
                ViaPolyV(:,3) = zeros(length(ViaPolyV(:,1)),1);
                SurfViaPoly = antenna.Polygon('Vertices',ViaPolyV);
                warning(orig_state);
            else
                SurfViaPoly = [];
            end
        end
        function ViaHolePoly = CreateViaVertices(~,surfIdx,viaIdx)
            Viaseparator = [nan,nan];
            % Return the vertices with nan seperator
            [ViaxValues,ViayValues] = getSurfaceViaPolygonData(int32(surfIdx), int32(viaIdx));
            ViaVertices = [ViaxValues(:), ViayValues(:)];
            ViaVertices = [ViaVertices; Viaseparator];
            ViaHolePoly = ViaVertices;


            % [ViaxValues,ViayValues] = getSurfaceViaPolygonData(int32(surfIdx), int32(viaIdx));
            % fillViashape = polyshape(ViaxValues(:,1),ViayValues(:,1));
            % ViaHolePoly = fillViashape;%union(RHolePoly,fillRHshape);
        end
    end

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

            % Copyright 2023 The MathWorks, Inc.

            surfInd = obj.PrivateSurfaceInd;
            ViaShape = CreateSurfaceVia(obj,surfInd);

            if ~isempty(ViaShape)
                S = ViaShape;
            else
                S = [];
            end
        end
    end
end
function mustBeValidNumber(SurfObj,value)
SurfaceInd = value;
SurfaceIndExp = SurfObj.SurfaceInfo.SurfaceIndex;
if any(SurfaceInd==SurfaceIndExp)
    value = value;  %#ok<ASGSL>
else
    eid = 'Value:notValid';
    msg = getString(message('rfpcb:rfpcberrors:SurfaceIndex',num2str(SurfaceIndExp')));
    throwAsCaller(MException(eid,msg));
end
end