public function generate($length = 16, $alpha = 0.6, $numeric = 0.2, $other = 0.2)
    {
        $chars = array();

        //~ Alphabetic characters
        for ($index = 0, $max = ceil($alpha * $length); $index < $max; $index++) {
            if ((bool) rand(0, 1)) {
                $char = rand(65, 90); // Upper
            } else {
                $char = rand(97, 122); // Lower
            }

            $chars[] = chr($char);
        }

        //~ Alphabetic characters
        for ($index = 0, $max = ceil($numeric * $length); $index < $max; $index++) {
            $char    = rand(48, 57); // Number
            $chars[] = chr($char);
        }

        //~ Other printable chars
        for ($index = 0, $max = ceil($other * $length); $index < $max; $index++) {

            switch ((int) rand(1, 4)) {
                case 1:
                    $char = rand(33, 47);
                    break;
                case 2:
                    $char = rand(58, 64);
                    break;
                case 3:
                    $char = rand(91, 96);
                    break;
                case 4:
                default:
                    $char = rand(123, 126);
                    break;
            }

            $chars[] = chr($char);
        }

        shuffle($chars);

        $this->password = implode('', array_slice($chars, 0, 16));

        return $this;
    }