typedef NS_OPTIONS(NSUInteger, SToolBarIconType) {
    SToolBarIconTypeUndefined = 0,
    SToolBarIconTypeMedia  = 1 << 1,
    SToolBarIconTypeVoice  = 1 << 2,
    SToolBarIconTypeSend   = 1 << 3,
    SToolBarIconTypeCount  = 3
};
@import Foundation;

NS_ASSUME_NONNULL_BEGIN

@interface SToolBarIconOption : NSObject

#pragma mark - Methods

- (void)addIcon:(SToolBarIconType)iconOption;
- (SToolBarIconType)iconAt:(NSUInteger)iconIndex;
- (NSUInteger)numberOfIcons;

@end

NS_ASSUME_NONNULL_END
#import "SToolBarIconOption.h"

@interface SToolBarIconOption ()

@property (nonatomic, assign) NSUInteger count;
@property (nonatomic, assign) NSUInteger iconOptions;

@end

@implementation SToolBarIconOption

#pragma mark - SToolBarIconOption (Public Methods)

- (NSUInteger)numberOfIcons
{
    NSUInteger numberOfIcons = 0;
    
    if (self.iconOptions > 0) {
        NSUInteger numberOfBits = log2(self.iconOptions);
        NSUInteger numberOfIconsDouble = numberOfBits / SToolBarIconTypeCount;
        if (numberOfIconsDouble <= 2 && numberOfIconsDouble > 0) {
            numberOfIcons = 1;
        } else {
            numberOfIcons = numberOfIconsDouble / 2;
            if (numberOfBits % SToolBarIconTypeCount > 0) {
                numberOfIcons++;
            }
        }
    }
    
    return numberOfIcons;
}

- (void)addIcon:(SInputToolBarIconType)iconOption
{
    self.count++;
    
    NSUInteger iconOrderInBit = 1 << self.count;
    
    NSUInteger orderedIconOption = (iconOrderInBit << SToolBarIconTypeCount) | iconOption;
    
    if (self.count == 1) {
        self.iconOptions = orderedIconOption;
    } else {
        self.iconOptions = self.iconOptions << (2 * SToolBarIconTypeCount);
        self.iconOptions = self.iconOptions | orderedIconOption;
    }
}

- (SToolBarIconOptions)iconAt:(NSUInteger)iconIndex
{
    NSUInteger iconPosition = iconIndex + 1;
    
    if (self.iconOptions == 0) {
        return SToolBarIconTypeUndefined;
    }
    
    if (self.numberOfIcons == 1) {
        if (iconPosition == 1) {
            return [self retrieveIconOption:self.iconOptions];
        }
        
        return SToolBarIconTypeUndefined;
    }

    NSUInteger iconPositionInBit = 1 << SToolBarIconTypeCount;
    
    BOOL foundIcon = NO;
    while (shiftedIconOption > 0) {
        if (iconPositionInBit & shiftedIconOption) {
            foundIcon = YES;
            break;
        }
        
        shiftedIconOption = shiftedIconOption >> (2 * SToolBarIconTypeCount);
        shiftedIconOptionCount += (2 * SToolBarIconTypeCount);
    }
    
    if (!foundIcon) {
        return SToolBarIconTypeUndefined;
    }
    
    shiftedIconOptionCount -= SToolBarIconTypeCount;
    shiftedIconOption = self.iconOptions >> shiftedIconOptionCount;
    
    return [self retrieveIconOption:shiftedIconOption];
}

#pragma mark - SToolBarIconOption (Private Methods)

- (SToolBarIconType)retrieveIconOption:(SToolBarIconType)option
{
    if (option & SToolBarIconTypeMedia) {
        return SToolBarIconTypeMedia;
    }
    
    if (option & SToolBarIconTypeVoice) {
        return SToolBarIconTypeVoice;
    }
    
    if (option & SToolBarIconTypeSend) {
        return SToolBarIconTypeSend;
    }
    
    return SToolBarIconTypeUndefined;
}

@end
Advertisements