function zigbeeMoveBulbColor(bulb, newColorX, newColorY, transitionTime, varargin)
%

% Copyright 2017 The MathWorks, Inc.

  if nargin == 5
    level = varargin{1};
    str = 'Move to Level';
  else
    level = 10;
    str = 'Move to Color';
  end

  bulbPatch = findall(bulb, 'Tag', 'bulbPatch');
  
  text = annotation(bulb, 'textbox', [0.29 0 0.6 0.1], 'str', str, ...
    'LineStyle', 'none', 'FontSize', 16);
  
  new_x = newColorX/65536;
  new_y = newColorY/65536;
  
  initRGB = bulbPatch.FaceColor;
  [init_x, init_y] = rgb2xyY(initRGB);
    
  updatesPerDecisecond = 10;
  for theta = 0 : (1/(transitionTime*updatesPerDecisecond)) : 1
    % time is in 1/10 of a second. Do 10 update for each such decisecond
    curr_x = init_x + theta*(new_x - init_x);
    curr_y = init_y + theta*(new_y - init_y);
    curr_rgb = xyY2rgb(curr_x, curr_y, level);
    bulbPatch.FaceColor = curr_rgb;
    
    pause(0.1/updatesPerDecisecond);
  end
  
  delete(text);
end

function rgb = xyY2rgb(x, y, level)

  % convert XY from CIE 1931 Color Space to RGB  
  z = 1 - x - y;
  
  Y = level*y; % arbitrary luminance (level control cluster)
  X = Y*x/y;
  Z = Y*z/y;
  
  XYZ2RGB = [0.41847  -0.15866  -0.082835; ...
            -0.091169 0.25243   0.015708; ...
             0.00092090 -0.0025498 0.17860];
             
  RGB = XYZ2RGB*[X; Y; Z];
  
  rgb = min(max(RGB', 0), 1); % trim RGB in [0, 1]

end

function [x, y] = rgb2xyY(rgb)

  RGB2XYZ = [0.49 0.31 0.2; ...
            0.17697 0.8124 0.01063; ...
             0 0.01 0.99]/0.17697;
           
  XYZ = RGB2XYZ * rgb';
  X = XYZ(1);
  Y = XYZ(2);
  
  x = X/(sum(XYZ));
  y = Y/(sum(XYZ));
  
end