function removeCustomTerrain(terrainName)
%removeCustomTerrain   Remove use of custom terrain data
%   removeCustomTerrain(NAME) removes use of the custom terrain data
%   specified by NAME, where NAME is a string scalar or character vector.
%   The terrain data specified by NAME must have been previously added
%   using addCustomTerrain. Call removeCustomTerrain to remove custom
%   terrain data that is no longer used.
%
%   % Example: Import DTED data and use in Site Viewer
%
%   % Add terrain for a region around Boulder, CO. The DTED file was 
%   % downloaded from the "SRTM Void Filled" data set available from the 
%   % U.S. Geological Survey.
%   dtedfile = "n39_w106_3arc_v2.dt1";
%   attribution = "SRTM 3 arc-second resolution. Data available " + ...
%      "from the U.S. Geological Survey.";
%   addCustomTerrain("southboulder",dtedfile,"Attribution",attribution)
%
%   % Specify custom terrain data with Site Viewer using the name above
%   % and show South Boulder Peak
%   viewer = siteviewer("Terrain","southboulder");
%   southboulderpeak = txsite("Name","South Boulder Peak", ...
%      "Latitude",39.95384, ...
%      "Longitude",-105.29916);
%   show(southboulderpeak)
%
%   % Remove custom terrain data
%   close(viewer)
%   removeCustomTerrain("southboulder")
%
%   See also siteviewer, addCustomTerrain

% Copyright 2018-2020 The MathWorks, Inc.

    validateattributes(terrainName, {'char','string'}, {'scalartext'}, ...
        'removeCustomTerrain','',1);
    terrainName = char(terrainName);

    % Name cannot match a factory choice
    lowerTerrainName = lower(terrainName);
    factoryTerrain = string(terrain.internal.TerrainSource.terrainchoices('factory'));
    if ismember(lowerTerrainName, factoryTerrain)
        error(message('shared_terrain:terrain:RemoveFactoryTerrain', lowerTerrainName));
    end

    % Name must be case-insensitive match for a custom terrain name
    s = settings;
    terrainSettings = s.shared.terrain;
    terrainOptions = string(properties(terrainSettings));
    [ismem, ind] = ismember(lowerTerrainName, lower(terrainOptions));
    if ~ismem
        error(message('shared_terrain:terrain:TerrainNameDoesNotExist', terrainName));
    end
    
    % Terrain cannot be in use by an open Viewer
    if exist("globe.internal.GlobeViewer","class")
        globeviewers = globe.internal.GlobeViewer.all;
        checkViewers(globeviewers, lowerTerrainName, terrainName)
    end
    
    % Remove corresponding cached terrain source
    sources = terrain.internal.TerrainSource.InstanceCache;
    if isKey(sources, lowerTerrainName)
        sources.remove(lowerTerrainName);
    end

    % Delete settings group
    terrainToRemove = terrainOptions(ind);
    writeLocation = terrainSettings.(terrainToRemove).Location.ActiveValue;
    maxZoomLevel = terrainSettings.(terrainToRemove).MaxZoomLevel.ActiveValue;
    terrainSettings.removeGroup(terrainToRemove)

    % Delete contents of write location that were generated by Tiler
    for zoomLevel = maxZoomLevel:-1:0
        zoomFolder = fullfile(writeLocation, string(zoomLevel));
        if exist(zoomFolder,'dir')
            rmdir(zoomFolder,'s');
        end
    end
    layerJSONFile = fullfile(writeLocation, 'layer.json');
    if exist(layerJSONFile,'file')
        delete(layerJSONFile);
    end
end

function checkViewers(viewers, lowerTerrainName, terrainName)
    for k = 1:numel(viewers)
       sv = viewers(k);
       if sv.Visible && strcmpi(sv.Terrain, lowerTerrainName)
           error(message('shared_terrain:terrain:RemoveTerrainInUse', terrainName));
       end
    end
end
