Maximal Skittle Enjoyment You've been given a bag of Skittles.  Everybody knows that in order to appreciate the different flavors the most, you need to rotate between the flavors.

Basics:


You can only eat 1 skittle at a time
The order that you eat your skittles must be periodic.  
Each period cannot contain a particular flavor more than once.
Your bag only has so many skittles.  You cannot eat more of a particular flavor of skittle than appears in your bag.
You want to eat as many skittles as you can (it may not always be possible)


Examples:

Lets say you start with 3 Red, 2 Blue, and 3 Green skittles:

R B G R B G R G       Invalid:  The last R must be followed by a B, not a G
R B G R B G R         Valid, but sub-optimal
R R R                 Valid, but sub-optimal
R G B R G B R G       Valid and optimal
G R B G R B G R       Also valid and optimal (there are multiple good solutions)


Input/Output


You are passed a non-empty list of positive integers for the color counts.  (The above example would be [3,2,3]).  
You need to return a list containing valid and optimal ordering.
Instead of using colors, you will use the indices from input list.  (The last example output above would be [2,0,1,2,0,1,2,0]).
Your output may be 0-indexed or 1-indexed.  My examples will be 0-indexed


Test Cases

1                          0
4                          0 0 0 0
4 1                        0 0 0 0
3 1                        0 1 0                   or  0 0 0
5 2 2                      0 1 2 0 1 2 0
2 3 5                      2 1 0 2 1 0 2 1         or  1 2 0 1 2 0 1 2
2 4 5                      2 1 2 1 2 1 2 1 2
3 4 5                      2 1 0 2 1 0 2 1 0 2 1   or  1 2 0 1 2 0 1 2 0 1 2
1 1 1 1 1 6                5 0 1 2 3 4 5           (lots of other solutions)
1 1 1 1 1 8                5 5 5 5 5 5 5 5
2 4 6 8                    3 2 1 3 2 1 3 2 1 3 2 1 3 2


This is a code-golf, so make your solutions as short as possible in your favorite language!
JavaScript (ES6), 177 175 bytes

a=&gt;a.map((n,i)=&gt;[n,l=i]).sort((a,b)=&gt;a[0]-b[0]).reduce((P,x,i,a)=&gt;(v=a.reduce((p,c,j)=&gt;j&lt;i?p:p+Math.min(c[0],x[0]+1),0))&gt;m?[...Array(m=v)].map((_,k)=&gt;a[l-k%(l+1-i)][1]):P,m=0)


Formatted and commented

a =&gt; a                              // given an array a:
.map((n, i) =&gt; [n, l = i])          // map it to [value, index] arrays / set l = length - 1
.sort((a, b) =&gt; a[0] - b[0])        // sort it by values in ascending order
.reduce((P, x, i, a) =&gt;             // for each reference entry x at position i:
  (v = a.reduce((p, c, j) =&gt;        //   for each entry c at position j:
    j &lt; i ?                         //     if c is before x:
      p                             //       keep the previous sum (which is 0)
    :                               //     else:
      p + Math.min(c[0], x[0] + 1), //       add minimum(value[j], value[i] + 1)
    0                               //   initialize the sum at 0
  )) &gt; m ?                          //   if the new sum v is better than our current best m:
    [...Array(m = v)].map((_, k) =&gt; //     update m to v and update the result to an array
      a[l - k % (l + 1 - i)][1]     //     of length m filled with indices picked repeatedly
    )                               //     between i and l
  :                                 //   else:
    P,                              //     keep the previous result
  m = 0                             // start with best score m = 0
)                                   // the final result is returned by the outer reduce()


Used formula

Below is a table showing how the formula F(i, j) = minimum(value[j], value[i] + 1) is working, here with i = 0 and the input [ 5, 2, 2 ].

This formula can be interpreted as follows: for each Skittle type, we can select no more than the number of the least available type plus one.

 j | Sorted    | value[j] | F(0, j) | Selected        | Output
   | input     |          |         | Skittles        | (starting from bottom left)
---+-----------+----------+---------+-----------------+-----------------------------
 0 | 2 2       |     2    |    2    | [2] [2]         | \
 1 | 1 1       |     2    |    2    | [1] [1]         |  &gt; 0 1 2 0 1 2 0
 2 | 0 0 0 0 0 |     5    |    3    | [0] [0] [0] 0 0 | /


Test cases



let f =

a=&gt;a.map((n,i)=&gt;[n,l=i]).sort((a,b)=&gt;a[0]-b[0]).reduce((P,x,i,a)=&gt;(v=a.reduce((p,c,j)=&gt;j&lt;i?p:p+Math.min(c[0],x[0]+1),0))&gt;m?[...Array(m=v)].map((_,k)=&gt;a[l-k%(l+1-i)][1]):P,m=0)

console.log(JSON.stringify(f([ 1                ]))); // 0
console.log(JSON.stringify(f([ 4                ]))); // 0 0 0 0
console.log(JSON.stringify(f([ 4, 1             ]))); // 0 0 0 0
console.log(JSON.stringify(f([ 3, 1             ]))); // 0 1 0
console.log(JSON.stringify(f([ 5, 2, 2          ]))); // 0 2 1 0 2 1 0
console.log(JSON.stringify(f([ 2, 3, 5          ]))); // 2 1 0 2 1 0 2 1
console.log(JSON.stringify(f([ 2, 4, 5          ]))); // 2 1 2 1 2 1 2 1 2
console.log(JSON.stringify(f([ 3, 4, 5          ]))); // 2 1 0 2 1 0 2 1 0 2 1
console.log(JSON.stringify(f([ 1, 1, 1, 1, 1, 6 ]))); // 5 4 3 2 1 0 5
console.log(JSON.stringify(f([ 1, 1, 1, 1, 1, 8 ]))); // 5 5 5 5 5 5 5 5
console.log(JSON.stringify(f([ 2, 4, 6, 8       ]))); // 3 2 1 3 2 1 3 2 1 3 2 1 3 2